diff --git a/.github/workflows/license_header.yml b/.github/workflows/license_header.yml new file mode 100644 index 0000000000..51b8172825 --- /dev/null +++ b/.github/workflows/license_header.yml @@ -0,0 +1,26 @@ +name: check license headers +on: + push: + branches: + - "**" + +jobs: + check-license-headers: + runs-on: ubuntu-20.04 + steps: + - name: Checkout github repo (+ download lfs dependencies) + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install click + - name: Check licenses header + run: | + python license_checker_and_adder.py --path=../antarest/ --action=check-strict + python license_checker_and_adder.py --path=../tests/ --action=check-strict + python license_checker_and_adder.py --path=../webapp/src --action=check-strict + working-directory: scripts diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5a7b9ad212..7a590a8214 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,7 +53,7 @@ jobs: pip install -r requirements-dev.txt - name: Test with pytest run: | - pytest --cov antarest --cov-report xml + pytest --cov antarest --cov-report xml -n auto --dist=worksteal - name: Archive code coverage results if: matrix.os == 'ubuntu-20.04' uses: actions/upload-artifact@v4 diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000000..ff59d0d710 --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,25 @@ +Github identifiers of authors, in alphabetical order: + +3lbanna +a-zakir +cbion +flomnes +FrancoisJ +GPivette +hdinia +Hyralc +insatomcat +laurent-laporte-pro +mabw-rte +makdeuneuv +MartinBelthle +maugde +olfamizen +pl-buiquang +qdesmedt +romeoadanhounme +sgatto +skamril +sylvlecl +TLAIDI +Wintxer diff --git a/alembic/versions/dae93f1d9110_populate_tag_and_study_tag_tables_with_.py b/alembic/versions/dae93f1d9110_populate_tag_and_study_tag_tables_with_.py index 6fbb060115..7be22d1e24 100644 --- a/alembic/versions/dae93f1d9110_populate_tag_and_study_tag_tables_with_.py +++ b/alembic/versions/dae93f1d9110_populate_tag_and_study_tag_tables_with_.py @@ -7,7 +7,6 @@ """ import collections import itertools -import json import secrets import typing as t @@ -16,6 +15,7 @@ from sqlalchemy.engine import Connection # type: ignore from antarest.study.css4_colors import COLOR_NAMES +from antarest.core.serialization import from_json, to_json # revision identifiers, used by Alembic. revision = "dae93f1d9110" @@ -34,7 +34,7 @@ def _avoid_duplicates(tags: t.Iterable[str]) -> t.Sequence[str]: def _load_patch_obj(patch: t.Optional[str]) -> t.MutableMapping[str, t.Any]: """Load the patch object from the `patch` field in the `study_additional_data` table.""" - obj: t.MutableMapping[str, t.Any] = json.loads(patch or "{}") + obj: t.MutableMapping[str, t.Any] = from_json(patch or "{}") obj["study"] = obj.get("study") or {} obj["study"]["tags"] = _avoid_duplicates(obj["study"].get("tags") or []) return obj @@ -113,7 +113,7 @@ def downgrade() -> None: objects_by_ids[study_id] = obj # Updating objects in the `study_additional_data` table - bulk_patches = [{"study_id": id_, "patch": json.dumps(obj)} for id_, obj in objects_by_ids.items()] + bulk_patches = [{"study_id": id_, "patch": to_json(obj)} for id_, obj in objects_by_ids.items()] if bulk_patches: sql = sa.text("UPDATE study_additional_data SET patch = :patch WHERE study_id = :study_id") connexion.execute(sql, *bulk_patches) diff --git a/antarest/__init__.py b/antarest/__init__.py index 2e8b12e6da..823a3a566a 100644 --- a/antarest/__init__.py +++ b/antarest/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Antares Web @@ -7,9 +19,9 @@ # Standard project metadata -__version__ = "2.17.5" +__version__ = "2.17.6" __author__ = "RTE, Antares Web Team" -__date__ = "2024-08-02" +__date__ = "2024-09-25" # noinspection SpellCheckingInspection __credits__ = "(c) Réseau de Transport de l’Électricité (RTE)" diff --git a/antarest/core/__init__.py b/antarest/core/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/__init__.py +++ b/antarest/core/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/application.py b/antarest/core/application.py new file mode 100644 index 0000000000..3f09bd4102 --- /dev/null +++ b/antarest/core/application.py @@ -0,0 +1,48 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from dataclasses import dataclass +from typing import Optional + +from fastapi import APIRouter, FastAPI + + +@dataclass(frozen=True) +class AppBuildContext: + """ + Base elements of the application, for use at construction time: + - app: the actual fastapi application, where middlewares, exception handlers, etc. may be added + - api_root: the route under which all API and WS endpoints must be registered + + API routes should not be added straight to app, but under api_root instead, + so that they are correctly prefixed if needed (/api for standalone mode). + + Warning: the inclusion of api_root must happen AFTER all subroutes + have been registered, hence the build method. + """ + + app: FastAPI + api_root: APIRouter + + def build(self) -> FastAPI: + """ + Finalizes the app construction by including the API route. + Must be performed AFTER all subroutes have been added. + """ + self.app.include_router(self.api_root) + return self.app + + +def create_app_ctxt(app: FastAPI, api_root: Optional[APIRouter] = None) -> AppBuildContext: + if not api_root: + api_root = APIRouter() + return AppBuildContext(app, api_root) diff --git a/antarest/core/cache/__init__.py b/antarest/core/cache/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/cache/__init__.py +++ b/antarest/core/cache/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/cache/business/__init__.py b/antarest/core/cache/business/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/cache/business/__init__.py +++ b/antarest/core/cache/business/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/cache/business/local_chache.py b/antarest/core/cache/business/local_chache.py index 7b65e755bd..ac2a026db5 100644 --- a/antarest/core/cache/business/local_chache.py +++ b/antarest/core/cache/business/local_chache.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import threading import time diff --git a/antarest/core/cache/business/redis_cache.py b/antarest/core/cache/business/redis_cache.py index 176e583b76..7793f280c7 100644 --- a/antarest/core/cache/business/redis_cache.py +++ b/antarest/core/cache/business/redis_cache.py @@ -1,4 +1,15 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Optional @@ -7,6 +18,7 @@ from antarest.core.interfaces.cache import ICache from antarest.core.model import JSON +from antarest.core.serialization import from_json logger = logging.getLogger(__name__) @@ -28,7 +40,7 @@ def put(self, id: str, data: JSON, duration: int = 3600) -> None: redis_element = RedisCacheElement(duration=duration, data=data) redis_key = f"cache:{id}" logger.info(f"Adding cache key {id}") - self.redis.set(redis_key, redis_element.json()) + self.redis.set(redis_key, redis_element.model_dump_json()) self.redis.expire(redis_key, duration) def get(self, id: str, refresh_timeout: Optional[int] = None) -> Optional[JSON]: @@ -37,7 +49,7 @@ def get(self, id: str, refresh_timeout: Optional[int] = None) -> Optional[JSON]: logger.info(f"Trying to retrieve cache key {id}") if result is not None: logger.info(f"Cache key {id} found") - json_result = json.loads(result) + json_result = from_json(result) redis_element = RedisCacheElement(duration=json_result["duration"], data=json_result["data"]) self.redis.expire( redis_key, diff --git a/antarest/core/cache/main.py b/antarest/core/cache/main.py index 8cc4a6a3b2..c707732fec 100644 --- a/antarest/core/cache/main.py +++ b/antarest/core/cache/main.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import Optional diff --git a/antarest/core/config.py b/antarest/core/config.py index d7b7ed1243..4b85331d6a 100644 --- a/antarest/core/config.py +++ b/antarest/core/config.py @@ -1,6 +1,19 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import multiprocessing import tempfile from dataclasses import asdict, dataclass, field +from enum import Enum from pathlib import Path from typing import Dict, List, Optional @@ -12,6 +25,12 @@ DEFAULT_WORKSPACE_NAME = "default" +class Launcher(str, Enum): + SLURM = "slurm" + LOCAL = "local" + DEFAULT = "default" + + @dataclass(frozen=True) class ExternalAuthConfig: """ @@ -387,7 +406,7 @@ def __post_init__(self) -> None: msg = f"Invalid configuration: {self.default=} must be one of {possible!r}" raise ValueError(msg) - def get_nb_cores(self, launcher: str) -> "NbCoresConfig": + def get_nb_cores(self, launcher: Launcher) -> "NbCoresConfig": """ Retrieve the number of cores configuration for a given launcher: "local" or "slurm". If "default" is specified, retrieve the configuration of the default launcher. @@ -404,12 +423,12 @@ def get_nb_cores(self, launcher: str) -> "NbCoresConfig": """ config_map = {"local": self.local, "slurm": self.slurm} config_map["default"] = config_map[self.default] - launcher_config = config_map.get(launcher) + launcher_config = config_map.get(launcher.value) if launcher_config is None: - raise InvalidConfigurationError(launcher) + raise InvalidConfigurationError(launcher.value) return launcher_config.nb_cores - def get_time_limit(self, launcher: str) -> TimeLimitConfig: + def get_time_limit(self, launcher: Launcher) -> 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. @@ -426,7 +445,7 @@ def get_time_limit(self, launcher: str) -> TimeLimitConfig: """ config_map = {"local": self.local, "slurm": self.slurm} config_map["default"] = config_map[self.default] - launcher_config = config_map.get(launcher) + launcher_config = config_map.get(launcher.value) if launcher_config is None: raise InvalidConfigurationError(launcher) return launcher_config.time_limit @@ -574,6 +593,7 @@ class Config: cache: CacheConfig = CacheConfig() tasks: TaskConfig = TaskConfig() root_path: str = "" + api_prefix: str = "" @classmethod def from_dict(cls, data: JSON) -> "Config": @@ -592,6 +612,7 @@ def from_dict(cls, data: JSON) -> "Config": cache=CacheConfig.from_dict(data["cache"]) if "cache" in data else defaults.cache, tasks=TaskConfig.from_dict(data["tasks"]) if "tasks" in data else defaults.tasks, root_path=data.get("root_path", defaults.root_path), + api_prefix=data.get("api_prefix", defaults.api_prefix), ) @classmethod diff --git a/antarest/core/configdata/__init__.py b/antarest/core/configdata/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/configdata/__init__.py +++ b/antarest/core/configdata/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/configdata/model.py b/antarest/core/configdata/model.py index cb58784493..3e0d6b970e 100644 --- a/antarest/core/configdata/model.py +++ b/antarest/core/configdata/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from enum import Enum from typing import Any, Optional diff --git a/antarest/core/configdata/repository.py b/antarest/core/configdata/repository.py index fe785038c4..3b7aea6ada 100644 --- a/antarest/core/configdata/repository.py +++ b/antarest/core/configdata/repository.py @@ -1,10 +1,22 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from operator import and_ from typing import Optional from antarest.core.configdata.model import ConfigData from antarest.core.jwt import DEFAULT_ADMIN_USER from antarest.core.model import JSON +from antarest.core.serialization import from_json, to_json_string from antarest.core.utils.fastapi_sqlalchemy import db @@ -31,14 +43,14 @@ def get(self, key: str, owner: Optional[int] = None) -> Optional[ConfigData]: def get_json(self, key: str, owner: Optional[int] = None) -> Optional[JSON]: configdata = self.get(key, owner) if configdata: - data: JSON = json.loads(configdata.value) + data: JSON = from_json(configdata.value) return data return None def put_json(self, key: str, data: JSON, owner: Optional[int] = None) -> None: configdata = ConfigData( key=key, - value=json.dumps(data), + value=to_json_string(data), owner=owner or DEFAULT_ADMIN_USER.id, ) configdata = db.session.merge(configdata) diff --git a/antarest/core/core_blueprint.py b/antarest/core/core_blueprint.py index 5eac42ce3b..27f6591109 100644 --- a/antarest/core/core_blueprint.py +++ b/antarest/core/core_blueprint.py @@ -1,15 +1,23 @@ -import logging +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any -from fastapi import APIRouter, Depends +from fastapi import APIRouter from pydantic import BaseModel from antarest.core.config import Config -from antarest.core.jwt import JWTUser -from antarest.core.requests import UserHasNotPermissionError from antarest.core.utils.web import APITag from antarest.core.version_info import VersionInfoDTO, get_commit_id, get_dependencies -from antarest.login.auth import Auth class StatusDTO(BaseModel): @@ -24,7 +32,6 @@ def create_utils_routes(config: Config) -> APIRouter: config: main server configuration """ bp = APIRouter() - auth = Auth(config) @bp.get("/health", tags=[APITag.misc], response_model=StatusDTO) def health() -> Any: @@ -54,15 +61,4 @@ def version_info() -> Any: dependencies=get_dependencies(), ) - @bp.get("/kill", include_in_schema=False) - def kill_worker( - current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: - if not current_user.is_site_admin(): - raise UserHasNotPermissionError() - logging.getLogger(__name__).critical("Killing the worker") - # PyInstaller modifies the behavior of built-in functions, such as `exit`. - # It is advisable to use `sys.exit` or raise the `SystemExit` exception instead. - raise SystemExit(f"Worker killed by the user #{current_user.id}") - return bp diff --git a/antarest/core/exceptions.py b/antarest/core/exceptions.py index adb38cd21b..af5639b5ff 100644 --- a/antarest/core/exceptions.py +++ b/antarest/core/exceptions.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import typing as t from http import HTTPStatus @@ -331,6 +343,16 @@ def __init__(self, is_variant: bool) -> None: super().__init__(HTTPStatus.EXPECTATION_FAILED, "Upgrade not supported for parent of variants") +class FileDeletionNotAllowed(HTTPException): + """ + Exception raised when deleting a file or a folder which isn't inside the 'User' folder. + """ + + def __init__(self, message: str) -> None: + msg = f"Raw deletion failed because {message}" + super().__init__(HTTPStatus.FORBIDDEN, msg) + + class ReferencedObjectDeletionNotAllowed(HTTPException): """ Exception raised when a binding constraint is not allowed to be deleted because it references diff --git a/antarest/core/filesystem_blueprint.py b/antarest/core/filesystem_blueprint.py index bf247978b2..d625d19c07 100644 --- a/antarest/core/filesystem_blueprint.py +++ b/antarest/core/filesystem_blueprint.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Filesystem Blueprint """ @@ -11,21 +23,21 @@ import typing_extensions as te from fastapi import APIRouter, Depends, HTTPException -from pydantic import BaseModel, Extra, Field +from pydantic import BaseModel, Field from starlette.responses import PlainTextResponse, StreamingResponse from antarest.core.config import Config from antarest.core.utils.web import APITag from antarest.login.auth import Auth -FilesystemName = te.Annotated[str, Field(regex=r"^\w+$", description="Filesystem name")] -MountPointName = te.Annotated[str, Field(regex=r"^\w+$", description="Mount point name")] +FilesystemName = te.Annotated[str, Field(pattern=r"^\w+$", description="Filesystem name")] +MountPointName = te.Annotated[str, Field(pattern=r"^\w+$", description="Mount point name")] class FilesystemDTO( BaseModel, - extra=Extra.forbid, - schema_extra={ + extra="forbid", + json_schema_extra={ "example": { "name": "ws", "mount_dirs": { @@ -50,8 +62,8 @@ class FilesystemDTO( class MountPointDTO( BaseModel, - extra=Extra.forbid, - schema_extra={ + extra="forbid", + json_schema_extra={ "example": { "name": "default", "path": "/path/to/workspaces/internal_studies", @@ -77,10 +89,10 @@ class MountPointDTO( name: MountPointName path: Path = Field(description="Full path of the mount point in Antares Web Server") - total_bytes: int = Field(0, description="Total size of the mount point in bytes") - used_bytes: int = Field(0, description="Used size of the mount point in bytes") - free_bytes: int = Field(0, description="Free size of the mount point in bytes") - message: str = Field("", description="A message describing the status of the mount point") + total_bytes: int = Field(default=0, description="Total size of the mount point in bytes") + used_bytes: int = Field(default=0, description="Used size of the mount point in bytes") + free_bytes: int = Field(default=0, description="Free size of the mount point in bytes") + message: str = Field(default="", description="A message describing the status of the mount point") @classmethod async def from_path(cls, name: str, path: Path) -> "MountPointDTO": @@ -98,8 +110,8 @@ async def from_path(cls, name: str, path: Path) -> "MountPointDTO": class FileInfoDTO( BaseModel, - extra=Extra.forbid, - schema_extra={ + extra="forbid", + json_schema_extra={ "example": { "path": "/path/to/workspaces/internal_studies/5a503c20-24a3-4734-9cf8-89565c9db5ec/study.antares", "file_type": "file", @@ -130,12 +142,12 @@ class FileInfoDTO( path: Path = Field(description="Full path of the file or directory in Antares Web Server") file_type: str = Field(description="Type of the file or directory") - file_count: int = Field(1, description="Number of files and folders in the directory (1 for files)") - size_bytes: int = Field(0, description="Size of the file or total size of the directory in bytes") + file_count: int = Field(default=1, description="Number of files and folders in the directory (1 for files)") + size_bytes: int = Field(default=0, description="Size of the file or total size of the directory in bytes") created: datetime.datetime = Field(description="Creation date of the file or directory (local time)") modified: datetime.datetime = Field(description="Last modification date of the file or directory (local time)") accessed: datetime.datetime = Field(description="Last access date of the file or directory (local time)") - message: str = Field("OK", description="A message describing the status of the file") + message: str = Field(default="OK", description="A message describing the status of the file") @classmethod async def from_path(cls, full_path: Path, *, details: bool = False) -> "FileInfoDTO": @@ -148,6 +160,7 @@ async def from_path(cls, full_path: Path, *, details: bool = False) -> "FileInfo path=full_path, file_type="unknown", file_count=0, # missing + size_bytes=0, # missing created=datetime.datetime.min, modified=datetime.datetime.min, accessed=datetime.datetime.min, @@ -162,6 +175,7 @@ async def from_path(cls, full_path: Path, *, details: bool = False) -> "FileInfo created=datetime.datetime.fromtimestamp(file_stat.st_ctime), modified=datetime.datetime.fromtimestamp(file_stat.st_mtime), accessed=datetime.datetime.fromtimestamp(file_stat.st_atime), + message="OK", ) if stat.S_ISDIR(file_stat.st_mode): diff --git a/antarest/core/filetransfer/__init__.py b/antarest/core/filetransfer/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/filetransfer/__init__.py +++ b/antarest/core/filetransfer/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/filetransfer/main.py b/antarest/core/filetransfer/main.py index f345d88150..3583dc5701 100644 --- a/antarest/core/filetransfer/main.py +++ b/antarest/core/filetransfer/main.py @@ -1,7 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.filetransfer.repository import FileDownloadRepository from antarest.core.filetransfer.service import FileTransferManager @@ -10,10 +23,10 @@ def build_filetransfer_service( - application: Optional[FastAPI], event_bus: IEventBus, config: Config + app_ctxt: Optional[AppBuildContext], event_bus: IEventBus, config: Config ) -> FileTransferManager: ftm = FileTransferManager(repository=FileDownloadRepository(), event_bus=event_bus, config=config) - if application: - application.include_router(create_file_transfer_api(ftm, config)) + if app_ctxt: + app_ctxt.api_root.include_router(create_file_transfer_api(ftm, config)) return ftm diff --git a/antarest/core/filetransfer/model.py b/antarest/core/filetransfer/model.py index bbb61c00b6..72463e0bad 100644 --- a/antarest/core/filetransfer/model.py +++ b/antarest/core/filetransfer/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import uuid from http import HTTPStatus from http.client import HTTPException @@ -29,7 +41,7 @@ class FileDownloadDTO(BaseModel): id: str name: str filename: str - expiration_date: Optional[str] + expiration_date: Optional[str] = None ready: bool failed: bool = False error_message: str = "" diff --git a/antarest/core/filetransfer/repository.py b/antarest/core/filetransfer/repository.py index 0d466fcdc0..3df0594b80 100644 --- a/antarest/core/filetransfer/repository.py +++ b/antarest/core/filetransfer/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List, Optional from antarest.core.filetransfer.model import FileDownload diff --git a/antarest/core/filetransfer/service.py b/antarest/core/filetransfer/service.py index 80a81e6927..dffb5a4908 100644 --- a/antarest/core/filetransfer/service.py +++ b/antarest/core/filetransfer/service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import logging import os diff --git a/antarest/core/filetransfer/web.py b/antarest/core/filetransfer/web.py index 968e2e30d4..6fce2e834a 100644 --- a/antarest/core/filetransfer/web.py +++ b/antarest/core/filetransfer/web.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from typing import Any, List diff --git a/antarest/core/interfaces/__init__.py b/antarest/core/interfaces/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/interfaces/__init__.py +++ b/antarest/core/interfaces/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/interfaces/cache.py b/antarest/core/interfaces/cache.py index 3fce146145..95d6497864 100644 --- a/antarest/core/interfaces/cache.py +++ b/antarest/core/interfaces/cache.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from abc import abstractmethod from enum import Enum from typing import List, Optional diff --git a/antarest/core/interfaces/eventbus.py b/antarest/core/interfaces/eventbus.py index 7463cfcafe..10965ea831 100644 --- a/antarest/core/interfaces/eventbus.py +++ b/antarest/core/interfaces/eventbus.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from abc import ABC, abstractmethod from enum import Enum from typing import Any, Awaitable, Callable, List, Optional diff --git a/antarest/core/interfaces/service.py b/antarest/core/interfaces/service.py index c80baee508..2e735cbbe5 100644 --- a/antarest/core/interfaces/service.py +++ b/antarest/core/interfaces/service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import threading from abc import ABC, abstractmethod diff --git a/antarest/core/jwt.py b/antarest/core/jwt.py index 16849fa9f0..b42cc3273b 100644 --- a/antarest/core/jwt.py +++ b/antarest/core/jwt.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List, Union from pydantic import BaseModel diff --git a/antarest/core/logging/__init__.py b/antarest/core/logging/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/logging/__init__.py +++ b/antarest/core/logging/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/logging/utils.py b/antarest/core/logging/utils.py index b0e5227ea3..991f21b846 100644 --- a/antarest/core/logging/utils.py +++ b/antarest/core/logging/utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import logging.config import re diff --git a/antarest/core/maintenance/__init__.py b/antarest/core/maintenance/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/maintenance/__init__.py +++ b/antarest/core/maintenance/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/maintenance/main.py b/antarest/core/maintenance/main.py index c5fd2b6c6c..8717150d07 100644 --- a/antarest/core/maintenance/main.py +++ b/antarest/core/maintenance/main.py @@ -1,7 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.interfaces.cache import ICache from antarest.core.interfaces.eventbus import DummyEventBusService, IEventBus @@ -11,7 +24,7 @@ def build_maintenance_manager( - application: Optional[FastAPI], + app_ctxt: Optional[AppBuildContext], config: Config, cache: ICache, event_bus: IEventBus = DummyEventBusService(), @@ -19,7 +32,7 @@ def build_maintenance_manager( repository = MaintenanceRepository() service = MaintenanceService(config, repository, event_bus, cache) - if application: - application.include_router(create_maintenance_api(service, config)) + if app_ctxt: + app_ctxt.api_root.include_router(create_maintenance_api(service, config)) return service diff --git a/antarest/core/maintenance/model.py b/antarest/core/maintenance/model.py index b8485f12b2..c133e4ea9f 100644 --- a/antarest/core/maintenance/model.py +++ b/antarest/core/maintenance/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from enum import Enum diff --git a/antarest/core/maintenance/repository.py b/antarest/core/maintenance/repository.py index 530d6a857d..1a69da65c6 100644 --- a/antarest/core/maintenance/repository.py +++ b/antarest/core/maintenance/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional from antarest.core.configdata.model import ConfigData, ConfigDataAppKeys diff --git a/antarest/core/maintenance/service.py b/antarest/core/maintenance/service.py index 7faeb6557b..4e4cecc24b 100644 --- a/antarest/core/maintenance/service.py +++ b/antarest/core/maintenance/service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import shutil import time diff --git a/antarest/core/maintenance/web.py b/antarest/core/maintenance/web.py index a9837788b5..ed6e28cf9f 100644 --- a/antarest/core/maintenance/web.py +++ b/antarest/core/maintenance/web.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import Any diff --git a/antarest/core/model.py b/antarest/core/model.py index 4c8c0d5f0e..b500e9a5c5 100644 --- a/antarest/core/model.py +++ b/antarest/core/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import enum from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union @@ -9,7 +21,7 @@ JSON = Dict[str, Any] ELEMENT = Union[str, int, float, bool, bytes] -SUB_JSON = Union[ELEMENT, JSON, List, None] +SUB_JSON = Union[ELEMENT, JSON, List[Any], None] class PublicMode(str, enum.Enum): diff --git a/antarest/core/permissions.py b/antarest/core/permissions.py index 8ecba4d85f..55defacf7d 100644 --- a/antarest/core/permissions.py +++ b/antarest/core/permissions.py @@ -1,4 +1,17 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging +import typing as t from antarest.core.jwt import JWTUser from antarest.core.model import PermissionInfo, PublicMode, StudyPermissionType @@ -7,8 +20,8 @@ logger = logging.getLogger(__name__) -permission_matrix = { - StudyPermissionType.READ: { +permission_matrix: t.Dict[str, t.Dict[str, t.Sequence[t.Union[RoleType, PublicMode]]]] = { + StudyPermissionType.READ.value: { "roles": [ RoleType.ADMIN, RoleType.RUNNER, @@ -22,15 +35,15 @@ PublicMode.READ, ], }, - StudyPermissionType.RUN: { + StudyPermissionType.RUN.value: { "roles": [RoleType.ADMIN, RoleType.RUNNER, RoleType.WRITER], "public_modes": [PublicMode.FULL, PublicMode.EDIT, PublicMode.EXECUTE], }, - StudyPermissionType.WRITE: { + StudyPermissionType.WRITE.value: { "roles": [RoleType.ADMIN, RoleType.WRITER], "public_modes": [PublicMode.FULL, PublicMode.EDIT], }, - StudyPermissionType.MANAGE_PERMISSIONS: { + StudyPermissionType.MANAGE_PERMISSIONS.value: { "roles": [RoleType.ADMIN], "public_modes": [], }, @@ -65,11 +78,11 @@ def check_permission( allowed_roles = permission_matrix[permission]["roles"] group_permission = any( - role in allowed_roles # type: ignore + role in allowed_roles for role in [group.role for group in (user.groups or []) if group.id in permission_info.groups] ) if group_permission: return True allowed_public_modes = permission_matrix[permission]["public_modes"] - return permission_info.public_mode in allowed_public_modes # type: ignore + return permission_info.public_mode in allowed_public_modes diff --git a/antarest/core/persistence.py b/antarest/core/persistence.py index 67e4e532c8..5bc80c4e98 100644 --- a/antarest/core/persistence.py +++ b/antarest/core/persistence.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import os from io import StringIO diff --git a/antarest/core/requests.py b/antarest/core/requests.py index d33285c7ab..d276f79dca 100644 --- a/antarest/core/requests.py +++ b/antarest/core/requests.py @@ -1,5 +1,19 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +import typing as t +from collections import OrderedDict from dataclasses import dataclass -from typing import Optional +from typing import Any, Generator, Tuple from fastapi import HTTPException from markupsafe import escape @@ -17,13 +31,52 @@ } +class CaseInsensitiveDict(t.MutableMapping[str, t.Any]): # copy of the requests class to avoid importing the package + def __init__(self, data=None, **kwargs) -> None: # type: ignore + self._store: OrderedDict[str, t.Any] = OrderedDict() + if data is None: + data = {} + self.update(data, **kwargs) + + def __setitem__(self, key: str, value: t.Any) -> None: + self._store[key.lower()] = (key, value) + + def __getitem__(self, key: str) -> t.Any: + return self._store[key.lower()][1] + + def __delitem__(self, key: str) -> None: + del self._store[key.lower()] + + def __iter__(self) -> t.Any: + return (casedkey for casedkey, mappedvalue in self._store.values()) + + def __len__(self) -> int: + return len(self._store) + + def lower_items(self) -> Generator[Tuple[Any, Any], Any, None]: + return ((lowerkey, keyval[1]) for (lowerkey, keyval) in self._store.items()) + + def __eq__(self, other: t.Any) -> bool: + if isinstance(other, t.Mapping): + other = CaseInsensitiveDict(other) + else: + return NotImplemented + return dict(self.lower_items()) == dict(other.lower_items()) + + def copy(self) -> "CaseInsensitiveDict": + return CaseInsensitiveDict(self._store.values()) + + def __repr__(self) -> str: + return str(dict(self.items())) + + @dataclass class RequestParameters: """ DTO object to handle data inside request to send to service """ - user: Optional[JWTUser] = None + user: t.Optional[JWTUser] = None def get_user_id(self) -> str: return str(escape(str(self.user.id))) if self.user else "Unknown" diff --git a/antarest/core/roles.py b/antarest/core/roles.py index 778ae44df2..232b5fa524 100644 --- a/antarest/core/roles.py +++ b/antarest/core/roles.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import enum import functools diff --git a/antarest/core/serialization/__init__.py b/antarest/core/serialization/__init__.py new file mode 100644 index 0000000000..6368c02f1e --- /dev/null +++ b/antarest/core/serialization/__init__.py @@ -0,0 +1,34 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. +import typing as t + +import pydantic + +ADAPTER: pydantic.TypeAdapter[t.Any] = pydantic.TypeAdapter( + type=t.Any, config=pydantic.config.ConfigDict(ser_json_inf_nan="constants") +) # ser_json_inf_nan="constants" means infinity and NaN values will be serialized as `Infinity` and `NaN`. + + +# These utility functions allow to serialize with pydantic instead of using the built-in python "json" library. +# Since pydantic v2 is written in RUST it's way faster. + + +def from_json(data: t.Union[str, bytes, bytearray]) -> t.Dict[str, t.Any]: + return ADAPTER.validate_json(data) # type: ignore + + +def to_json(data: t.Any, indent: t.Optional[int] = None) -> bytes: + return ADAPTER.dump_json(data, indent=indent) + + +def to_json_string(data: t.Any, indent: t.Optional[int] = None) -> str: + return to_json(data, indent=indent).decode("utf-8") diff --git a/antarest/core/swagger.py b/antarest/core/swagger.py index 3d10993a31..3d1b62441a 100644 --- a/antarest/core/swagger.py +++ b/antarest/core/swagger.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, List, Tuple from fastapi import FastAPI diff --git a/antarest/core/tasks/__init__.py b/antarest/core/tasks/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/tasks/__init__.py +++ b/antarest/core/tasks/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/tasks/main.py b/antarest/core/tasks/main.py index 0aa2f6c670..74685ba836 100644 --- a/antarest/core/tasks/main.py +++ b/antarest/core/tasks/main.py @@ -1,7 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.interfaces.eventbus import DummyEventBusService, IEventBus from antarest.core.tasks.repository import TaskJobRepository @@ -10,14 +23,14 @@ def build_taskjob_manager( - application: Optional[FastAPI], + app_ctxt: Optional[AppBuildContext], config: Config, event_bus: IEventBus = DummyEventBusService(), ) -> ITaskService: repository = TaskJobRepository() service = TaskJobService(config, repository, event_bus) - if application: - application.include_router(create_tasks_api(service, config)) + if app_ctxt: + app_ctxt.api_root.include_router(create_tasks_api(service, config)) return service diff --git a/antarest/core/tasks/model.py b/antarest/core/tasks/model.py index 601e0db8ce..a7ca9aedb9 100644 --- a/antarest/core/tasks/model.py +++ b/antarest/core/tasks/model.py @@ -1,9 +1,21 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import uuid from datetime import datetime from enum import Enum -from pydantic import BaseModel, Extra +from pydantic import BaseModel from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, Sequence, String # type: ignore from sqlalchemy.engine.base import Engine # type: ignore from sqlalchemy.orm import relationship, sessionmaker # type: ignore @@ -25,6 +37,7 @@ class TaskType(str, Enum): SCAN = "SCAN" UPGRADE_STUDY = "UPGRADE_STUDY" THERMAL_CLUSTER_SERIES_GENERATION = "THERMAL_CLUSTER_SERIES_GENERATION" + SNAPSHOT_CLEARING = "SNAPSHOT_CLEARING" class TaskStatus(Enum): @@ -44,43 +57,43 @@ def is_final(self) -> bool: ] -class TaskResult(BaseModel, extra=Extra.forbid): +class TaskResult(BaseModel, extra="forbid"): success: bool message: str # Can be used to store json serialized result - return_value: t.Optional[str] + return_value: t.Optional[str] = None -class TaskLogDTO(BaseModel, extra=Extra.forbid): +class TaskLogDTO(BaseModel, extra="forbid"): id: str message: str -class CustomTaskEventMessages(BaseModel, extra=Extra.forbid): +class CustomTaskEventMessages(BaseModel, extra="forbid"): start: str running: str end: str -class TaskEventPayload(BaseModel, extra=Extra.forbid): +class TaskEventPayload(BaseModel, extra="forbid"): id: str message: str -class TaskDTO(BaseModel, extra=Extra.forbid): +class TaskDTO(BaseModel, extra="forbid"): id: str name: str - owner: t.Optional[int] + owner: t.Optional[int] = None status: TaskStatus creation_date_utc: str - completion_date_utc: t.Optional[str] - result: t.Optional[TaskResult] - logs: t.Optional[t.List[TaskLogDTO]] + completion_date_utc: t.Optional[str] = None + result: t.Optional[TaskResult] = None + logs: t.Optional[t.List[TaskLogDTO]] = None type: t.Optional[str] = None ref_id: t.Optional[str] = None -class TaskListFilter(BaseModel, extra=Extra.forbid): +class TaskListFilter(BaseModel, extra="forbid"): status: t.List[TaskStatus] = [] name: t.Optional[str] = None type: t.List[TaskType] = [] @@ -158,6 +171,15 @@ class TaskJob(Base): # type: ignore study: "Study" = relationship("Study", back_populates="jobs", uselist=False) def to_dto(self, with_logs: bool = False) -> TaskDTO: + result = None + if self.completion_date: + assert self.result_status is not None + assert self.result_msg is not None + result = TaskResult( + success=self.result_status, + message=self.result_msg, + return_value=self.result, + ) return TaskDTO( id=self.id, owner=self.owner_id, @@ -165,13 +187,7 @@ def to_dto(self, with_logs: bool = False) -> TaskDTO: completion_date_utc=str(self.completion_date) if self.completion_date else None, name=self.name, status=TaskStatus(self.status), - result=TaskResult( - success=self.result_status, - message=self.result_msg, - return_value=self.result, - ) - if self.completion_date - else None, + result=result, logs=sorted([log.to_dto() for log in self.logs], key=lambda log: log.id) if with_logs else None, type=self.type, ref_id=self.ref_id, diff --git a/antarest/core/tasks/repository.py b/antarest/core/tasks/repository.py index 9a579ba241..0a2028db33 100644 --- a/antarest/core/tasks/repository.py +++ b/antarest/core/tasks/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import typing as t from http import HTTPStatus diff --git a/antarest/core/tasks/service.py b/antarest/core/tasks/service.py index 07832e7365..e4855e01c3 100644 --- a/antarest/core/tasks/service.py +++ b/antarest/core/tasks/service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import logging import time @@ -132,7 +144,7 @@ def _create_awaiter( res_wrapper: t.List[TaskResult], ) -> t.Callable[[Event], t.Awaitable[None]]: async def _await_task_end(event: Event) -> None: - task_event = WorkerTaskResult.parse_obj(event.payload) + task_event = WorkerTaskResult.model_validate(event.payload) if task_event.task_id == task_id: res_wrapper.append(task_event.task_result) @@ -240,7 +252,7 @@ def _launch_task( message=custom_event_messages.start if custom_event_messages is not None else f"Task {task.id} added", - ).dict(), + ).model_dump(), permissions=PermissionInfo(owner=request_params.user.impersonator), ) ) @@ -349,7 +361,7 @@ def _run_task( message=custom_event_messages.running if custom_event_messages is not None else f"Task {task_id} is running", - ).dict(), + ).model_dump(), permissions=PermissionInfo(public_mode=PublicMode.READ), channel=EventChannelDirectory.TASK + task_id, ) @@ -395,7 +407,7 @@ def _run_task( if custom_event_messages is not None else f"Task {task_id} {event_msg}" ), - ).dict(), + ).model_dump(), permissions=PermissionInfo(public_mode=PublicMode.READ), channel=EventChannelDirectory.TASK + task_id, ) @@ -420,7 +432,7 @@ def _run_task( self.event_bus.push( Event( type=EventType.TASK_FAILED, - payload=TaskEventPayload(id=task_id, message=message).dict(), + payload=TaskEventPayload(id=task_id, message=message).model_dump(), permissions=PermissionInfo(public_mode=PublicMode.READ), channel=EventChannelDirectory.TASK + task_id, ) diff --git a/antarest/core/tasks/web.py b/antarest/core/tasks/web.py index 83c75ea23b..4d8fa77a93 100644 --- a/antarest/core/tasks/web.py +++ b/antarest/core/tasks/web.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import concurrent.futures import http import logging diff --git a/antarest/core/utils/__init__.py b/antarest/core/utils/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/core/utils/__init__.py +++ b/antarest/core/utils/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/core/utils/fastapi_sqlalchemy/LICENSE b/antarest/core/utils/fastapi_sqlalchemy/LICENSE new file mode 100644 index 0000000000..577fc21f6c --- /dev/null +++ b/antarest/core/utils/fastapi_sqlalchemy/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Michael Freeborn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/antarest/core/utils/fastapi_sqlalchemy/README.md b/antarest/core/utils/fastapi_sqlalchemy/README.md index 78c02a32a5..fae88f5abc 100644 --- a/antarest/core/utils/fastapi_sqlalchemy/README.md +++ b/antarest/core/utils/fastapi_sqlalchemy/README.md @@ -1,3 +1,4 @@ # FastAPI-SQLAlchemy -Forked from https://github.com/mfreeborn/fastapi-sqlalchemy \ No newline at end of file +Forked from https://github.com/mfreeborn/fastapi-sqlalchemy, +licensed under MIT license, see [LICENSE](LICENSE). diff --git a/antarest/core/utils/fastapi_sqlalchemy/middleware.py b/antarest/core/utils/fastapi_sqlalchemy/middleware.py index 9a98b4ef1b..dcc1f95b25 100644 --- a/antarest/core/utils/fastapi_sqlalchemy/middleware.py +++ b/antarest/core/utils/fastapi_sqlalchemy/middleware.py @@ -12,7 +12,7 @@ from antarest.core.utils.fastapi_sqlalchemy.exceptions import MissingSessionError, SessionNotInitialisedError -_Session: sessionmaker = None +_Session: Optional[sessionmaker] = None _session: ContextVar[Optional[Session]] = ContextVar("_session", default=None) @@ -93,4 +93,4 @@ def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: _session.reset(self.token) -db: DBSessionMeta = DBSession +db: Type[DBSession] = DBSession diff --git a/antarest/core/utils/string.py b/antarest/core/utils/string.py index 49221438d2..35c5e75541 100644 --- a/antarest/core/utils/string.py +++ b/antarest/core/utils/string.py @@ -1,3 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + + def to_pascal_case(value: str) -> str: return "".join(word.capitalize() for word in value.split("_")) diff --git a/antarest/core/utils/utils.py b/antarest/core/utils/utils.py index 6f41c6947c..89002edcfe 100644 --- a/antarest/core/utils/utils.py +++ b/antarest/core/utils/utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import base64 import glob import http diff --git a/antarest/core/utils/web.py b/antarest/core/utils/web.py index 2990b05c41..aeae230ce9 100644 --- a/antarest/core/utils/web.py +++ b/antarest/core/utils/web.py @@ -1,3 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + + class APITag: users = "Users" launcher = "Launch Studies" diff --git a/antarest/core/version_info.py b/antarest/core/version_info.py index 8b1b50d84b..ea96eaf4ef 100644 --- a/antarest/core/version_info.py +++ b/antarest/core/version_info.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Python module that is dedicated to printing application version and dependencies information """ @@ -16,7 +28,7 @@ class VersionInfoDTO(BaseModel): dependencies: Dict[str, str] class Config: - schema_extra = { + json_schema_extra = { "example": { "name": "AntaREST", "version": "2.13.2", diff --git a/antarest/dbmodel.py b/antarest/dbmodel.py index 4cd7c745ae..738134dadd 100644 --- a/antarest/dbmodel.py +++ b/antarest/dbmodel.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + # noinspection PyUnresolvedReferences from antarest.core.configdata import model as configdatamodel diff --git a/antarest/eventbus/__init__.py b/antarest/eventbus/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/eventbus/__init__.py +++ b/antarest/eventbus/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/eventbus/business/__init__.py b/antarest/eventbus/business/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/eventbus/business/__init__.py +++ b/antarest/eventbus/business/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/eventbus/business/interfaces.py b/antarest/eventbus/business/interfaces.py index b180775c4f..63a90b7ee5 100644 --- a/antarest/eventbus/business/interfaces.py +++ b/antarest/eventbus/business/interfaces.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import abc from abc import abstractmethod from typing import List, Optional diff --git a/antarest/eventbus/business/local_eventbus.py b/antarest/eventbus/business/local_eventbus.py index 3e9d146c30..bfe0e6992d 100644 --- a/antarest/eventbus/business/local_eventbus.py +++ b/antarest/eventbus/business/local_eventbus.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import Dict, List, Optional diff --git a/antarest/eventbus/business/redis_eventbus.py b/antarest/eventbus/business/redis_eventbus.py index 94d7f5a36c..f3642bf994 100644 --- a/antarest/eventbus/business/redis_eventbus.py +++ b/antarest/eventbus/business/redis_eventbus.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Optional, cast @@ -17,10 +29,10 @@ def __init__(self, redis_client: Redis) -> None: # type: ignore self.pubsub.subscribe(REDIS_STORE_KEY) def push_event(self, event: Event) -> None: - self.redis.publish(REDIS_STORE_KEY, event.json()) + self.redis.publish(REDIS_STORE_KEY, event.model_dump_json()) def queue_event(self, event: Event, queue: str) -> None: - self.redis.rpush(queue, event.json()) + self.redis.rpush(queue, event.model_dump_json()) def pull_queue(self, queue: str) -> Optional[Event]: event = self.redis.lpop(queue) diff --git a/antarest/eventbus/main.py b/antarest/eventbus/main.py index fcd3ba05a8..6ccf56e644 100644 --- a/antarest/eventbus/main.py +++ b/antarest/eventbus/main.py @@ -1,8 +1,21 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI from redis import Redis +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.eventbus.business.local_eventbus import LocalEventBus from antarest.eventbus.business.redis_eventbus import RedisEventBus @@ -11,7 +24,7 @@ def build_eventbus( - application: Optional[FastAPI], + app_ctxt: Optional[AppBuildContext], config: Config, autostart: bool = True, redis_client: Optional[Redis] = None, # type: ignore @@ -21,6 +34,6 @@ def build_eventbus( autostart, ) - if application: - configure_websockets(application, config, eventbus) + if app_ctxt: + configure_websockets(app_ctxt, config, eventbus) return eventbus diff --git a/antarest/eventbus/service.py b/antarest/eventbus/service.py index 5386bc8e2e..201efb3be6 100644 --- a/antarest/eventbus/service.py +++ b/antarest/eventbus/service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import asyncio import logging import random diff --git a/antarest/eventbus/web.py b/antarest/eventbus/web.py index cae0ffb99f..a04a4571bb 100644 --- a/antarest/eventbus/web.py +++ b/antarest/eventbus/web.py @@ -1,20 +1,33 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import dataclasses -import json import logging from enum import Enum from http import HTTPStatus from typing import List, Optional -from fastapi import Depends, FastAPI, HTTPException, Query -from fastapi_jwt_auth import AuthJWT # type: ignore +from fastapi import Depends, HTTPException, Query from pydantic import BaseModel from starlette.websockets import WebSocket, WebSocketDisconnect +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.interfaces.eventbus import Event, IEventBus from antarest.core.jwt import DEFAULT_ADMIN_USER, JWTUser from antarest.core.model import PermissionInfo, StudyPermissionType from antarest.core.permissions import check_permission +from antarest.core.serialization import to_json_string +from antarest.fastapi_jwt_auth import AuthJWT from antarest.login.auth import Auth logger = logging.getLogger(__name__) @@ -79,16 +92,16 @@ async def broadcast(self, message: str, permissions: PermissionInfo, channel: st await connection.websocket.send_text(message) -def configure_websockets(application: FastAPI, config: Config, event_bus: IEventBus) -> None: +def configure_websockets(app_ctxt: AppBuildContext, config: Config, event_bus: IEventBus) -> None: manager = ConnectionManager() async def send_event_to_ws(event: Event) -> None: - event_data = event.dict() + event_data = event.model_dump() del event_data["permissions"] del event_data["channel"] - await manager.broadcast(json.dumps(event_data), event.permissions, event.channel) + await manager.broadcast(to_json_string(event_data), event.permissions, event.channel) - @application.websocket("/ws") + @app_ctxt.api_root.websocket("/ws") async def connect( websocket: WebSocket, token: str = Query(...), diff --git a/antarest/fastapi_jwt_auth/LICENSE b/antarest/fastapi_jwt_auth/LICENSE new file mode 100644 index 0000000000..ad5e3c8004 --- /dev/null +++ b/antarest/fastapi_jwt_auth/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Nyoman Pradipta Dewantara + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/antarest/fastapi_jwt_auth/README.md b/antarest/fastapi_jwt_auth/README.md new file mode 100644 index 0000000000..c4dfd9017e --- /dev/null +++ b/antarest/fastapi_jwt_auth/README.md @@ -0,0 +1,4 @@ +# FastAPI JWT Auth + +Forked from https://github.com/IndominusByte/fastapi-jwt-auth, +licensed under MIT license, see [LICENSE](LICENSE). diff --git a/antarest/fastapi_jwt_auth/__init__.py b/antarest/fastapi_jwt_auth/__init__.py new file mode 100644 index 0000000000..a3748ffe33 --- /dev/null +++ b/antarest/fastapi_jwt_auth/__init__.py @@ -0,0 +1,7 @@ +"""FastAPI extension that provides JWT Auth support (secure, easy to use and lightweight)""" + +__version__ = "0.5.0" + +__all__ = ["AuthJWT"] + +from .auth_jwt import AuthJWT diff --git a/antarest/fastapi_jwt_auth/auth_config.py b/antarest/fastapi_jwt_auth/auth_config.py new file mode 100644 index 0000000000..55ca04a25d --- /dev/null +++ b/antarest/fastapi_jwt_auth/auth_config.py @@ -0,0 +1,114 @@ +from datetime import timedelta +from typing import Callable, List + +from pydantic import ValidationError + +from .config import LoadConfig + + +class AuthConfig: + _token = None + _token_location = {"headers"} + + _secret_key = None + _public_key = None + _private_key = None + _algorithm = "HS256" + _decode_algorithms = None + _decode_leeway = 0 + _encode_issuer = None + _decode_issuer = None + _decode_audience = None + _denylist_enabled = False + _denylist_token_checks = {"access", "refresh"} + _header_name = "Authorization" + _header_type = "Bearer" + _token_in_denylist_callback = None + _access_token_expires = timedelta(minutes=15) + _refresh_token_expires = timedelta(days=30) + + # option for create cookies + _access_cookie_key = "access_token_cookie" + _refresh_cookie_key = "refresh_token_cookie" + _access_cookie_path = "/" + _refresh_cookie_path = "/" + _cookie_max_age = None + _cookie_domain = None + _cookie_secure = False + _cookie_samesite = None + + # option for double submit csrf protection + _cookie_csrf_protect = True + _access_csrf_cookie_key = "csrf_access_token" + _refresh_csrf_cookie_key = "csrf_refresh_token" + _access_csrf_cookie_path = "/" + _refresh_csrf_cookie_path = "/" + _access_csrf_header_name = "X-CSRF-Token" + _refresh_csrf_header_name = "X-CSRF-Token" + _csrf_methods = {"POST", "PUT", "PATCH", "DELETE"} + + @property + def jwt_in_cookies(self) -> bool: + return "cookies" in self._token_location + + @property + def jwt_in_headers(self) -> bool: + return "headers" in self._token_location + + @classmethod + def load_config(cls, settings: Callable[..., List[tuple]]) -> "AuthConfig": + try: + config = LoadConfig(**{key.lower(): value for key, value in settings()}) + + cls._token_location = config.authjwt_token_location + cls._secret_key = config.authjwt_secret_key + cls._public_key = config.authjwt_public_key + cls._private_key = config.authjwt_private_key + cls._algorithm = config.authjwt_algorithm + cls._decode_algorithms = config.authjwt_decode_algorithms + cls._decode_leeway = config.authjwt_decode_leeway + cls._encode_issuer = config.authjwt_encode_issuer + cls._decode_issuer = config.authjwt_decode_issuer + cls._decode_audience = config.authjwt_decode_audience + cls._denylist_enabled = config.authjwt_denylist_enabled + cls._denylist_token_checks = config.authjwt_denylist_token_checks + cls._header_name = config.authjwt_header_name + cls._header_type = config.authjwt_header_type + cls._access_token_expires = config.authjwt_access_token_expires + cls._refresh_token_expires = config.authjwt_refresh_token_expires + # option for create cookies + cls._access_cookie_key = config.authjwt_access_cookie_key + cls._refresh_cookie_key = config.authjwt_refresh_cookie_key + cls._access_cookie_path = config.authjwt_access_cookie_path + cls._refresh_cookie_path = config.authjwt_refresh_cookie_path + cls._cookie_max_age = config.authjwt_cookie_max_age + cls._cookie_domain = config.authjwt_cookie_domain + cls._cookie_secure = config.authjwt_cookie_secure + cls._cookie_samesite = config.authjwt_cookie_samesite + # option for double submit csrf protection + cls._cookie_csrf_protect = config.authjwt_cookie_csrf_protect + cls._access_csrf_cookie_key = config.authjwt_access_csrf_cookie_key + cls._refresh_csrf_cookie_key = config.authjwt_refresh_csrf_cookie_key + cls._access_csrf_cookie_path = config.authjwt_access_csrf_cookie_path + cls._refresh_csrf_cookie_path = config.authjwt_refresh_csrf_cookie_path + cls._access_csrf_header_name = config.authjwt_access_csrf_header_name + cls._refresh_csrf_header_name = config.authjwt_refresh_csrf_header_name + cls._csrf_methods = config.authjwt_csrf_methods + except ValidationError as e: + raise e + except Exception: + raise TypeError("Config must be pydantic 'BaseSettings' or list of tuple") + + @classmethod + def token_in_denylist_loader(cls, callback: Callable[..., bool]) -> "AuthConfig": + """ + This decorator sets the callback function that will be called when + a protected endpoint is accessed and will check if the JWT has been + been revoked. By default, this callback is not used. + + *HINT*: The callback must be a function that takes decrypted_token argument, + args for object AuthJWT and this is not used, decrypted_token is decode + JWT (python dictionary) and returns *`True`* if the token has been deny, + or *`False`* otherwise. + """ + cls._token_in_denylist_callback = callback diff --git a/antarest/fastapi_jwt_auth/auth_jwt.py b/antarest/fastapi_jwt_auth/auth_jwt.py new file mode 100644 index 0000000000..19fa3173b4 --- /dev/null +++ b/antarest/fastapi_jwt_auth/auth_jwt.py @@ -0,0 +1,817 @@ +import hmac +import re +import uuid +from datetime import datetime, timedelta, timezone +from typing import Dict, Optional, Sequence, Union + +import jwt +from fastapi import Request, Response, WebSocket +from jwt.algorithms import has_crypto, requires_cryptography + +from .auth_config import AuthConfig +from .exceptions import ( + AccessTokenRequired, + CSRFError, + FreshTokenRequired, + InvalidHeaderError, + JWTDecodeError, + MissingTokenError, + RefreshTokenRequired, + RevokedTokenError, +) + +TYPE_ERROR_MSG = "The response must be an object response FastAPI" + + +class AuthJWT(AuthConfig): + def __init__(self, req: Request = None, res: Response = None): + """ + Get jwt header from incoming request or get + request and response object if jwt in the cookie + + :param req: all incoming request + :param res: response from endpoint + """ + if res and self.jwt_in_cookies: + self._response = res + + if req: + # get request object when cookies in token location + if self.jwt_in_cookies: + self._request = req + # get jwt in headers when headers in token location + if self.jwt_in_headers: + auth = req.headers.get(self._header_name.lower()) + if auth: + self._get_jwt_from_headers(auth) + + def _get_jwt_from_headers(self, auth: str) -> "AuthJWT": + """ + Get token from the headers + + :param auth: value from HeaderName + """ + header_name, header_type = self._header_name, self._header_type + + parts = auth.split() + + # Make sure the header is in a valid format that we are expecting, ie + if not header_type: + # : + if len(parts) != 1: + msg = "Bad {} header. Expected value ''".format(header_name) + raise InvalidHeaderError(status_code=422, message=msg) + self._token = parts[0] + else: + # : + if not re.match(r"{}\s".format(header_type), auth) or len(parts) != 2: + msg = "Bad {} header. Expected value '{} '".format(header_name, header_type) + raise InvalidHeaderError(status_code=422, message=msg) + self._token = parts[1] + + def _get_jwt_identifier(self) -> str: + return str(uuid.uuid4()) + + def _get_int_from_datetime(self, value: datetime) -> int: + """ + :param value: datetime with or without timezone, if don't contains timezone + it will managed as it is UTC + :return: Seconds since the Epoch + """ + if not isinstance(value, datetime): # pragma: no cover + raise TypeError("a datetime is required") + return int(value.timestamp()) + + def _get_secret_key(self, algorithm: str, process: str) -> str: + """ + Get key with a different algorithm + + :param algorithm: algorithm for decode and encode token + :param process: for indicating get key for encode or decode token + + :return: plain text or RSA depends on algorithm + """ + symmetric_algorithms, asymmetric_algorithms = {"HS256", "HS384", "HS512"}, requires_cryptography + + if algorithm not in symmetric_algorithms and algorithm not in asymmetric_algorithms: + raise ValueError("Algorithm {} could not be found".format(algorithm)) + + if algorithm in symmetric_algorithms: + if not self._secret_key: + raise RuntimeError("authjwt_secret_key must be set when using symmetric algorithm {}".format(algorithm)) + + return self._secret_key + + if algorithm in asymmetric_algorithms and not has_crypto: + raise RuntimeError( + "Missing dependencies for using asymmetric algorithms. run 'pip install fastapi-jwt-auth[asymmetric]'" + ) + + if process == "encode": + if not self._private_key: + raise RuntimeError( + "authjwt_private_key must be set when using asymmetric algorithm {}".format(algorithm) + ) + + return self._private_key + + if process == "decode": + if not self._public_key: + raise RuntimeError( + "authjwt_public_key must be set when using asymmetric algorithm {}".format(algorithm) + ) + + return self._public_key + + def _create_token( + self, + subject: Union[str, int], + type_token: str, + exp_time: Optional[int], + fresh: Optional[bool] = False, + algorithm: Optional[str] = None, + headers: Optional[Dict] = None, + issuer: Optional[str] = None, + audience: Optional[Union[str, Sequence[str]]] = None, + user_claims: Optional[Dict] = {}, + ) -> str: + """ + Create token for access_token and refresh_token (utf-8) + + :param subject: Identifier for who this token is for example id or username from database. + :param type_token: indicate token is access_token or refresh_token + :param exp_time: Set the duration of the JWT + :param fresh: Optional when token is access_token this param required + :param algorithm: algorithm allowed to encode the token + :param headers: valid dict for specifying additional headers in JWT header section + :param issuer: expected issuer in the JWT + :param audience: expected audience in the JWT + :param user_claims: Custom claims to include in this token. This data must be dictionary + + :return: Encoded token + """ + # Validation type data + if not isinstance(subject, (str, int)): + raise TypeError("subject must be a string or integer") + if not isinstance(fresh, bool): + raise TypeError("fresh must be a boolean") + if audience and not isinstance(audience, (str, list, tuple, set, frozenset)): + raise TypeError("audience must be a string or sequence") + if algorithm and not isinstance(algorithm, str): + raise TypeError("algorithm must be a string") + if user_claims and not isinstance(user_claims, dict): + raise TypeError("user_claims must be a dictionary") + + # Data section + reserved_claims = { + "sub": subject, + "iat": self._get_int_from_datetime(datetime.now(timezone.utc)), + "nbf": self._get_int_from_datetime(datetime.now(timezone.utc)), + "jti": self._get_jwt_identifier(), + } + + custom_claims = {"type": type_token} + + # for access_token only fresh needed + if type_token == "access": + custom_claims["fresh"] = fresh + # if cookie in token location and csrf protection enabled + if self.jwt_in_cookies and self._cookie_csrf_protect: + custom_claims["csrf"] = self._get_jwt_identifier() + + if exp_time: + reserved_claims["exp"] = exp_time + if issuer: + reserved_claims["iss"] = issuer + if audience: + reserved_claims["aud"] = audience + + algorithm = algorithm or self._algorithm + + secret_key = self._get_secret_key(algorithm, "encode") + + return jwt.encode( + {**reserved_claims, **custom_claims, **user_claims}, secret_key, algorithm=algorithm, headers=headers + ) + + def _has_token_in_denylist_callback(self) -> bool: + """ + Return True if token denylist callback set + """ + return self._token_in_denylist_callback is not None + + def _check_token_is_revoked(self, raw_token: Dict[str, Union[str, int, bool]]) -> None: + """ + Ensure that AUTHJWT_DENYLIST_ENABLED is true and callback regulated, and then + call function denylist callback with passing decode JWT, if true + raise exception Token has been revoked + """ + if not self._denylist_enabled: + return + + if not self._has_token_in_denylist_callback(): + raise RuntimeError( + "A token_in_denylist_callback must be provided via " + "the '@AuthJWT.token_in_denylist_loader' if " + "authjwt_denylist_enabled is 'True'" + ) + + if self._token_in_denylist_callback.__func__(raw_token): + raise RevokedTokenError(status_code=401, message="Token has been revoked") + + def _get_expired_time( + self, type_token: str, expires_time: Optional[Union[timedelta, int, bool]] = None + ) -> Union[None, int]: + """ + Dynamic token expired, if expires_time is False exp claim not created + + :param type_token: indicate token is access_token or refresh_token + :param expires_time: duration expired jwt + + :return: duration exp claim jwt + """ + if expires_time and not isinstance(expires_time, (timedelta, int, bool)): + raise TypeError("expires_time must be between timedelta, int, bool") + + if expires_time is not False: + if type_token == "access": + expires_time = expires_time or self._access_token_expires + if type_token == "refresh": + expires_time = expires_time or self._refresh_token_expires + + if expires_time is not False: + if isinstance(expires_time, bool): + if type_token == "access": + expires_time = self._access_token_expires + if type_token == "refresh": + expires_time = self._refresh_token_expires + if isinstance(expires_time, timedelta): + expires_time = int(expires_time.total_seconds()) + + return self._get_int_from_datetime(datetime.now(timezone.utc)) + expires_time + else: + return None + + def create_access_token( + self, + subject: Union[str, int], + fresh: Optional[bool] = False, + algorithm: Optional[str] = None, + headers: Optional[Dict] = None, + expires_time: Optional[Union[timedelta, int, bool]] = None, + audience: Optional[Union[str, Sequence[str]]] = None, + user_claims: Optional[Dict] = {}, + ) -> str: + """ + Create a access token with 15 minutes for expired time (default), + info for param and return check to function create token + + :return: hash token + """ + return self._create_token( + subject=subject, + type_token="access", + exp_time=self._get_expired_time("access", expires_time), + fresh=fresh, + algorithm=algorithm, + headers=headers, + audience=audience, + user_claims=user_claims, + issuer=self._encode_issuer, + ) + + def create_refresh_token( + self, + subject: Union[str, int], + algorithm: Optional[str] = None, + headers: Optional[Dict] = None, + expires_time: Optional[Union[timedelta, int, bool]] = None, + audience: Optional[Union[str, Sequence[str]]] = None, + user_claims: Optional[Dict] = {}, + ) -> str: + """ + Create a refresh token with 30 days for expired time (default), + info for param and return check to function create token + + :return: hash token + """ + return self._create_token( + subject=subject, + type_token="refresh", + exp_time=self._get_expired_time("refresh", expires_time), + algorithm=algorithm, + headers=headers, + audience=audience, + user_claims=user_claims, + ) + + def _get_csrf_token(self, encoded_token: str) -> str: + """ + Returns the CSRF double submit token from an encoded JWT. + + :param encoded_token: The encoded JWT + :return: The CSRF double submit token + """ + return self._verified_token(encoded_token)["csrf"] + + def set_access_cookies( + self, encoded_access_token: str, response: Optional[Response] = None, max_age: Optional[int] = None + ) -> None: + """ + Configures the response to set access token in a cookie. + this will also set the CSRF double submit values in a separate cookie + + :param encoded_access_token: The encoded access token to set in the cookies + :param response: The FastAPI response object to set the access cookies in + :param max_age: The max age of the cookie value should be the number of seconds (integer) + """ + if not self.jwt_in_cookies: + raise RuntimeWarning( + "set_access_cookies() called without 'authjwt_token_location' configured to use cookies" + ) + + if max_age and not isinstance(max_age, int): + raise TypeError("max_age must be a integer") + if response and not isinstance(response, Response): + raise TypeError(TYPE_ERROR_MSG) + + response = response or self._response + + # Set the access JWT in the cookie + response.set_cookie( + self._access_cookie_key, + encoded_access_token, + max_age=max_age or self._cookie_max_age, + path=self._access_cookie_path, + domain=self._cookie_domain, + secure=self._cookie_secure, + httponly=True, + samesite=self._cookie_samesite, + ) + + # If enabled, set the csrf double submit access cookie + if self._cookie_csrf_protect: + response.set_cookie( + self._access_csrf_cookie_key, + self._get_csrf_token(encoded_access_token), + max_age=max_age or self._cookie_max_age, + path=self._access_csrf_cookie_path, + domain=self._cookie_domain, + secure=self._cookie_secure, + httponly=False, + samesite=self._cookie_samesite, + ) + + def set_refresh_cookies( + self, encoded_refresh_token: str, response: Optional[Response] = None, max_age: Optional[int] = None + ) -> None: + """ + Configures the response to set refresh token in a cookie. + this will also set the CSRF double submit values in a separate cookie + + :param encoded_refresh_token: The encoded refresh token to set in the cookies + :param response: The FastAPI response object to set the refresh cookies in + :param max_age: The max age of the cookie value should be the number of seconds (integer) + """ + if not self.jwt_in_cookies: + raise RuntimeWarning( + "set_refresh_cookies() called without 'authjwt_token_location' configured to use cookies" + ) + + if max_age and not isinstance(max_age, int): + raise TypeError("max_age must be a integer") + if response and not isinstance(response, Response): + raise TypeError(TYPE_ERROR_MSG) + + response = response or self._response + + # Set the refresh JWT in the cookie + response.set_cookie( + self._refresh_cookie_key, + encoded_refresh_token, + max_age=max_age or self._cookie_max_age, + path=self._refresh_cookie_path, + domain=self._cookie_domain, + secure=self._cookie_secure, + httponly=True, + samesite=self._cookie_samesite, + ) + + # If enabled, set the csrf double submit refresh cookie + if self._cookie_csrf_protect: + response.set_cookie( + self._refresh_csrf_cookie_key, + self._get_csrf_token(encoded_refresh_token), + max_age=max_age or self._cookie_max_age, + path=self._refresh_csrf_cookie_path, + domain=self._cookie_domain, + secure=self._cookie_secure, + httponly=False, + samesite=self._cookie_samesite, + ) + + def unset_jwt_cookies(self, response: Optional[Response] = None) -> None: + """ + Unset (delete) all jwt stored in a cookie + + :param response: The FastAPI response object to delete the JWT cookies in. + """ + self.unset_access_cookies(response) + self.unset_refresh_cookies(response) + + def unset_access_cookies(self, response: Optional[Response] = None) -> None: + """ + Remove access token and access CSRF double submit from the response cookies + + :param response: The FastAPI response object to delete the access cookies in. + """ + if not self.jwt_in_cookies: + raise RuntimeWarning( + "unset_access_cookies() called without 'authjwt_token_location' configured to use cookies" + ) + + if response and not isinstance(response, Response): + raise TypeError(TYPE_ERROR_MSG) + + response = response or self._response + + response.delete_cookie(self._access_cookie_key, path=self._access_cookie_path, domain=self._cookie_domain) + + if self._cookie_csrf_protect: + response.delete_cookie( + self._access_csrf_cookie_key, path=self._access_csrf_cookie_path, domain=self._cookie_domain + ) + + def unset_refresh_cookies(self, response: Optional[Response] = None) -> None: + """ + Remove refresh token and refresh CSRF double submit from the response cookies + + :param response: The FastAPI response object to delete the refresh cookies in. + """ + if not self.jwt_in_cookies: + raise RuntimeWarning( + "unset_refresh_cookies() called without 'authjwt_token_location' configured to use cookies" + ) + + if response and not isinstance(response, Response): + raise TypeError(TYPE_ERROR_MSG) + + response = response or self._response + + response.delete_cookie(self._refresh_cookie_key, path=self._refresh_cookie_path, domain=self._cookie_domain) + + if self._cookie_csrf_protect: + response.delete_cookie( + self._refresh_csrf_cookie_key, path=self._refresh_csrf_cookie_path, domain=self._cookie_domain + ) + + def _verify_and_get_jwt_optional_in_cookies( + self, + request: Union[Request, WebSocket], + csrf_token: Optional[str] = None, + ) -> "AuthJWT": + """ + Optionally check if cookies have a valid access token. if an access token present in + cookies, self._token will set. raises exception error when an access token is invalid + or doesn't match with CSRF token double submit + + :param request: for identity get cookies from HTTP or WebSocket + :param csrf_token: the CSRF double submit token + """ + if not isinstance(request, (Request, WebSocket)): + raise TypeError("request must be an instance of 'Request' or 'WebSocket'") + + cookie_key = self._access_cookie_key + cookie = request.cookies.get(cookie_key) + if not isinstance(request, WebSocket): + csrf_token = request.headers.get(self._access_csrf_header_name) + + if cookie and self._cookie_csrf_protect and not csrf_token: + if isinstance(request, WebSocket) or request.method in self._csrf_methods: + raise CSRFError(status_code=401, message="Missing CSRF Token") + + # set token from cookie and verify jwt + self._token = cookie + self._verify_jwt_optional_in_request(self._token) + + decoded_token = self.get_raw_jwt() + + if decoded_token and self._cookie_csrf_protect and csrf_token: + if isinstance(request, WebSocket) or request.method in self._csrf_methods: + if "csrf" not in decoded_token: + raise JWTDecodeError(status_code=422, message="Missing claim: csrf") + if not hmac.compare_digest(csrf_token, decoded_token["csrf"]): + raise CSRFError(status_code=401, message="CSRF double submit tokens do not match") + + def _verify_and_get_jwt_in_cookies( + self, + type_token: str, + request: Union[Request, WebSocket], + csrf_token: Optional[str] = None, + fresh: Optional[bool] = False, + ) -> "AuthJWT": + """ + Check if cookies have a valid access or refresh token. if an token present in + cookies, self._token will set. raises exception error when an access or refresh token + is invalid or doesn't match with CSRF token double submit + + :param type_token: indicate token is access or refresh token + :param request: for identity get cookies from HTTP or WebSocket + :param csrf_token: the CSRF double submit token + :param fresh: check freshness token if True + """ + if type_token not in ["access", "refresh"]: + raise ValueError("type_token must be between 'access' or 'refresh'") + if not isinstance(request, (Request, WebSocket)): + raise TypeError("request must be an instance of 'Request' or 'WebSocket'") + + if type_token == "access": + cookie_key = self._access_cookie_key + cookie = request.cookies.get(cookie_key) + if not isinstance(request, WebSocket): + csrf_token = request.headers.get(self._access_csrf_header_name) + if type_token == "refresh": + cookie_key = self._refresh_cookie_key + cookie = request.cookies.get(cookie_key) + if not isinstance(request, WebSocket): + csrf_token = request.headers.get(self._refresh_csrf_header_name) + + if not cookie: + raise MissingTokenError(status_code=401, message="Missing cookie {}".format(cookie_key)) + + if self._cookie_csrf_protect and not csrf_token: + if isinstance(request, WebSocket) or request.method in self._csrf_methods: + raise CSRFError(status_code=401, message="Missing CSRF Token") + + # set token from cookie and verify jwt + self._token = cookie + self._verify_jwt_in_request(self._token, type_token, "cookies", fresh) + + decoded_token = self.get_raw_jwt() + + if self._cookie_csrf_protect and csrf_token: + if isinstance(request, WebSocket) or request.method in self._csrf_methods: + if "csrf" not in decoded_token: + raise JWTDecodeError(status_code=422, message="Missing claim: csrf") + if not hmac.compare_digest(csrf_token, decoded_token["csrf"]): + raise CSRFError(status_code=401, message="CSRF double submit tokens do not match") + + def _verify_jwt_optional_in_request(self, token: str) -> None: + """ + Optionally check if this request has a valid access token + + :param token: The encoded JWT + """ + if token: + self._verifying_token(token) + + if token and self.get_raw_jwt(token)["type"] != "access": + raise AccessTokenRequired(status_code=422, message="Only access tokens are allowed") + + def _verify_jwt_in_request( + self, token: str, type_token: str, token_from: str, fresh: Optional[bool] = False + ) -> None: + """ + Ensure that the requester has a valid token. this also check the freshness of the access token + + :param token: The encoded JWT + :param type_token: indicate token is access or refresh token + :param token_from: indicate token from headers cookies, websocket + :param fresh: check freshness token if True + """ + if type_token not in ["access", "refresh"]: + raise ValueError("type_token must be between 'access' or 'refresh'") + if token_from not in ["headers", "cookies", "websocket"]: + raise ValueError("token_from must be between 'headers', 'cookies', 'websocket'") + + if not token: + if token_from == "headers": + raise MissingTokenError(status_code=401, message="Missing {} Header".format(self._header_name)) + if token_from == "websocket": + raise MissingTokenError( + status_code=1008, message="Missing {} token from Query or Path".format(type_token) + ) + + # verify jwt + issuer = self._decode_issuer if type_token == "access" else None + self._verifying_token(token, issuer) + + if self.get_raw_jwt(token)["type"] != type_token: + msg = "Only {} tokens are allowed".format(type_token) + if type_token == "access": + raise AccessTokenRequired(status_code=422, message=msg) + if type_token == "refresh": + raise RefreshTokenRequired(status_code=422, message=msg) + + if fresh and not self.get_raw_jwt(token)["fresh"]: + raise FreshTokenRequired(status_code=401, message="Fresh token required") + + def _verifying_token(self, encoded_token: str, issuer: Optional[str] = None) -> None: + """ + Verified token and check if token is revoked + + :param encoded_token: token hash + :param issuer: expected issuer in the JWT + """ + raw_token = self._verified_token(encoded_token, issuer) + if raw_token["type"] in self._denylist_token_checks: + self._check_token_is_revoked(raw_token) + + def _verified_token(self, encoded_token: str, issuer: Optional[str] = None) -> Dict[str, Union[str, int, bool]]: + """ + Verified token and catch all error from jwt package and return decode token + + :param encoded_token: token hash + :param issuer: expected issuer in the JWT + + :return: raw data from the hash token in the form of a dictionary + """ + algorithms = self._decode_algorithms or [self._algorithm] + secret_key = self._get_secret_key(self._algorithm, "decode") + try: + return jwt.decode( + encoded_token, + secret_key, + issuer=issuer, + audience=self._decode_audience, + leeway=self._decode_leeway, + algorithms=algorithms, + ) + except Exception as err: + raise JWTDecodeError(status_code=422, message=str(err)) + + def jwt_required( + self, + auth_from: str = "request", + token: Optional[str] = None, + websocket: Optional[WebSocket] = None, + csrf_token: Optional[str] = None, + ) -> None: + """ + Only access token can access this function + + :param auth_from: for identity get token from HTTP or WebSocket + :param token: the encoded JWT, it's required if the protected endpoint use WebSocket to + authorization and get token from Query Url or Path + :param websocket: an instance of WebSocket, it's required if protected endpoint use a cookie to authorization + :param csrf_token: the CSRF double submit token. since WebSocket cannot add specifying additional headers + its must be passing csrf_token manually and can achieve by Query Url or Path + """ + if auth_from == "websocket": + if websocket: + self._verify_and_get_jwt_in_cookies("access", websocket, csrf_token) + else: + self._verify_jwt_in_request(token, "access", "websocket") + + if auth_from == "request": + if len(self._token_location) == 2: + if self._token and self.jwt_in_headers: + self._verify_jwt_in_request(self._token, "access", "headers") + if not self._token and self.jwt_in_cookies: + self._verify_and_get_jwt_in_cookies("access", self._request) + else: + if self.jwt_in_headers: + self._verify_jwt_in_request(self._token, "access", "headers") + if self.jwt_in_cookies: + self._verify_and_get_jwt_in_cookies("access", self._request) + + def jwt_optional( + self, + auth_from: str = "request", + token: Optional[str] = None, + websocket: Optional[WebSocket] = None, + csrf_token: Optional[str] = None, + ) -> None: + """ + If an access token in present in the request you can get data from get_raw_jwt() or get_jwt_subject(), + If no access token is present in the request, this endpoint will still be called, but + get_raw_jwt() or get_jwt_subject() will return None + + :param auth_from: for identity get token from HTTP or WebSocket + :param token: the encoded JWT, it's required if the protected endpoint use WebSocket to + authorization and get token from Query Url or Path + :param websocket: an instance of WebSocket, it's required if protected endpoint use a cookie to authorization + :param csrf_token: the CSRF double submit token. since WebSocket cannot add specifying additional headers + its must be passing csrf_token manually and can achieve by Query Url or Path + """ + if auth_from == "websocket": + if websocket: + self._verify_and_get_jwt_optional_in_cookies(websocket, csrf_token) + else: + self._verify_jwt_optional_in_request(token) + + if auth_from == "request": + if len(self._token_location) == 2: + if self._token and self.jwt_in_headers: + self._verify_jwt_optional_in_request(self._token) + if not self._token and self.jwt_in_cookies: + self._verify_and_get_jwt_optional_in_cookies(self._request) + else: + if self.jwt_in_headers: + self._verify_jwt_optional_in_request(self._token) + if self.jwt_in_cookies: + self._verify_and_get_jwt_optional_in_cookies(self._request) + + def jwt_refresh_token_required( + self, + auth_from: str = "request", + token: Optional[str] = None, + websocket: Optional[WebSocket] = None, + csrf_token: Optional[str] = None, + ) -> None: + """ + This function will ensure that the requester has a valid refresh token + + :param auth_from: for identity get token from HTTP or WebSocket + :param token: the encoded JWT, it's required if the protected endpoint use WebSocket to + authorization and get token from Query Url or Path + :param websocket: an instance of WebSocket, it's required if protected endpoint use a cookie to authorization + :param csrf_token: the CSRF double submit token. since WebSocket cannot add specifying additional headers + its must be passing csrf_token manually and can achieve by Query Url or Path + """ + if auth_from == "websocket": + if websocket: + self._verify_and_get_jwt_in_cookies("refresh", websocket, csrf_token) + else: + self._verify_jwt_in_request(token, "refresh", "websocket") + + if auth_from == "request": + if len(self._token_location) == 2: + if self._token and self.jwt_in_headers: + self._verify_jwt_in_request(self._token, "refresh", "headers") + if not self._token and self.jwt_in_cookies: + self._verify_and_get_jwt_in_cookies("refresh", self._request) + else: + if self.jwt_in_headers: + self._verify_jwt_in_request(self._token, "refresh", "headers") + if self.jwt_in_cookies: + self._verify_and_get_jwt_in_cookies("refresh", self._request) + + def fresh_jwt_required( + self, + auth_from: str = "request", + token: Optional[str] = None, + websocket: Optional[WebSocket] = None, + csrf_token: Optional[str] = None, + ) -> None: + """ + This function will ensure that the requester has a valid access token and fresh token + + :param auth_from: for identity get token from HTTP or WebSocket + :param token: the encoded JWT, it's required if the protected endpoint use WebSocket to + authorization and get token from Query Url or Path + :param websocket: an instance of WebSocket, it's required if protected endpoint use a cookie to authorization + :param csrf_token: the CSRF double submit token. since WebSocket cannot add specifying additional headers + its must be passing csrf_token manually and can achieve by Query Url or Path + """ + if auth_from == "websocket": + if websocket: + self._verify_and_get_jwt_in_cookies("access", websocket, csrf_token, True) + else: + self._verify_jwt_in_request(token, "access", "websocket", True) + + if auth_from == "request": + if len(self._token_location) == 2: + if self._token and self.jwt_in_headers: + self._verify_jwt_in_request(self._token, "access", "headers", True) + if not self._token and self.jwt_in_cookies: + self._verify_and_get_jwt_in_cookies("access", self._request, fresh=True) + else: + if self.jwt_in_headers: + self._verify_jwt_in_request(self._token, "access", "headers", True) + if self.jwt_in_cookies: + self._verify_and_get_jwt_in_cookies("access", self._request, fresh=True) + + def get_raw_jwt(self, encoded_token: Optional[str] = None) -> Optional[Dict[str, Union[str, int, bool]]]: + """ + this will return the python dictionary which has all of the claims of the JWT that is accessing the endpoint. + If no JWT is currently present, return None instead + + :param encoded_token: The encoded JWT from parameter + :return: claims of JWT + """ + token = encoded_token or self._token + + if token: + return self._verified_token(token) + return None + + def get_jti(self, encoded_token: str) -> str: + """ + Returns the JTI (unique identifier) of an encoded JWT + + :param encoded_token: The encoded JWT from parameter + :return: string of JTI + """ + return self._verified_token(encoded_token)["jti"] + + def get_jwt_subject(self) -> Optional[Union[str, int]]: + """ + this will return the subject of the JWT that is accessing this endpoint. + If no JWT is present, `None` is returned instead. + + :return: sub of JWT + """ + if self._token: + return self._verified_token(self._token)["sub"] + return None diff --git a/antarest/fastapi_jwt_auth/config.py b/antarest/fastapi_jwt_auth/config.py new file mode 100644 index 0000000000..f04ace9cd7 --- /dev/null +++ b/antarest/fastapi_jwt_auth/config.py @@ -0,0 +1,90 @@ +import typing as t +from datetime import timedelta +from typing import List, Optional, Sequence, Union + +from pydantic import BaseModel, StrictBool, StrictInt, StrictStr, ValidationError, field_validator, model_validator + + +class LoadConfig(BaseModel): + authjwt_token_location: Optional[t.Set[StrictStr]] = {"headers"} + authjwt_secret_key: Optional[StrictStr] = None + authjwt_public_key: Optional[StrictStr] = None + authjwt_private_key: Optional[StrictStr] = None + authjwt_algorithm: Optional[StrictStr] = "HS256" + authjwt_decode_algorithms: Optional[List[StrictStr]] = None + authjwt_decode_leeway: Optional[Union[StrictInt, timedelta]] = 0 + authjwt_encode_issuer: Optional[StrictStr] = None + authjwt_decode_issuer: Optional[StrictStr] = None + authjwt_decode_audience: Optional[Union[StrictStr, Sequence[StrictStr]]] = None + authjwt_denylist_enabled: Optional[StrictBool] = False + authjwt_denylist_token_checks: Optional[t.Set[StrictStr]] = {"access", "refresh"} + authjwt_header_name: Optional[StrictStr] = "Authorization" + authjwt_header_type: Optional[StrictStr] = "Bearer" + authjwt_access_token_expires: Optional[Union[StrictBool, StrictInt, timedelta]] = timedelta(minutes=15) + authjwt_refresh_token_expires: Optional[Union[StrictBool, StrictInt, timedelta]] = timedelta(days=30) + # option for create cookies + authjwt_access_cookie_key: Optional[StrictStr] = "access_token_cookie" + authjwt_refresh_cookie_key: Optional[StrictStr] = "refresh_token_cookie" + authjwt_access_cookie_path: Optional[StrictStr] = "/" + authjwt_refresh_cookie_path: Optional[StrictStr] = "/" + authjwt_cookie_max_age: Optional[StrictInt] = None + authjwt_cookie_domain: Optional[StrictStr] = None + authjwt_cookie_secure: Optional[StrictBool] = False + authjwt_cookie_samesite: Optional[StrictStr] = None + # option for double submit csrf protection + authjwt_cookie_csrf_protect: Optional[StrictBool] = True + authjwt_access_csrf_cookie_key: Optional[StrictStr] = "csrf_access_token" + authjwt_refresh_csrf_cookie_key: Optional[StrictStr] = "csrf_refresh_token" + authjwt_access_csrf_cookie_path: Optional[StrictStr] = "/" + authjwt_refresh_csrf_cookie_path: Optional[StrictStr] = "/" + authjwt_access_csrf_header_name: Optional[StrictStr] = "X-CSRF-Token" + authjwt_refresh_csrf_header_name: Optional[StrictStr] = "X-CSRF-Token" + authjwt_csrf_methods: Optional[t.Set[StrictStr]] = {"POST", "PUT", "PATCH", "DELETE"} + + @field_validator("authjwt_access_token_expires") + def validate_access_token_expires( + cls, v: Optional[Union[StrictBool, StrictInt, timedelta]] + ) -> Optional[Union[StrictBool, StrictInt, timedelta]]: + if v is True: + raise ValueError("The 'authjwt_access_token_expires' only accept value False (bool)") + return v + + @field_validator("authjwt_refresh_token_expires") + def validate_refresh_token_expires( + cls, v: Optional[Union[StrictBool, StrictInt, timedelta]] + ) -> Optional[Union[StrictBool, StrictInt, timedelta]]: + if v is True: + raise ValueError("The 'authjwt_refresh_token_expires' only accept value False (bool)") + return v + + @field_validator("authjwt_cookie_samesite") + def validate_cookie_samesite(cls, v: Optional[StrictStr]) -> Optional[StrictStr]: + if v not in ["strict", "lax", "none"]: + raise ValueError("The 'authjwt_cookie_samesite' must be between 'strict', 'lax', 'none'") + return v + + @model_validator(mode="before") + def check_type_validity(cls, values: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + for _ in values.get("authjwt_csrf_methods", []): + if _.upper() not in ["POST", "PUT", "PATCH", "DELETE"]: + raise ValidationError( + f"The 'authjwt_csrf_methods' must be between http request methods and it's {_.upper()}" + ) + + for _ in values.get("authjwt_cookie_samesite", []): + if _ not in ["strict", "lax", "none"]: + raise ValidationError( + f"The 'authjwt_cookie_samesite' must be between 'strict', 'lax', 'none' and it's {_}" + ) + + for _ in values.get("authjwt_token_location", []): + if _ not in ["headers", "cookies"]: + raise ValidationError( + f"The 'authjwt_token_location' must be between 'headers' or 'cookies' and it's {_}" + ) + + return values + + class Config: + str_min_length = 1 + str_strip_whitespace = True diff --git a/antarest/fastapi_jwt_auth/exceptions.py b/antarest/fastapi_jwt_auth/exceptions.py new file mode 100644 index 0000000000..1057571c0a --- /dev/null +++ b/antarest/fastapi_jwt_auth/exceptions.py @@ -0,0 +1,89 @@ +class AuthJWTException(Exception): + """ + Base except which all fastapi_jwt_auth errors extend + """ + + pass + + +class InvalidHeaderError(AuthJWTException): + """ + An error getting jwt in header or jwt header information from a request + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message + + +class JWTDecodeError(AuthJWTException): + """ + An error decoding a JWT + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message + + +class CSRFError(AuthJWTException): + """ + An error with CSRF protection + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message + + +class MissingTokenError(AuthJWTException): + """ + Error raised when token not found + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message + + +class RevokedTokenError(AuthJWTException): + """ + Error raised when a revoked token attempt to access a protected endpoint + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message + + +class AccessTokenRequired(AuthJWTException): + """ + Error raised when a valid, non-access JWT attempt to access an endpoint + protected by jwt_required, jwt_optional, fresh_jwt_required + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message + + +class RefreshTokenRequired(AuthJWTException): + """ + Error raised when a valid, non-refresh JWT attempt to access an endpoint + protected by jwt_refresh_token_required + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message + + +class FreshTokenRequired(AuthJWTException): + """ + Error raised when a valid, non-fresh JWT attempt to access an endpoint + protected by fresh_jwt_required + """ + + def __init__(self, status_code: int, message: str): + self.status_code = status_code + self.message = message diff --git a/antarest/front.py b/antarest/front.py new file mode 100644 index 0000000000..8de0f05e82 --- /dev/null +++ b/antarest/front.py @@ -0,0 +1,139 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. +""" +This module contains the logic necessary to serve both +the front-end application and the backend HTTP application. + +This includes: + - serving static frontend files + - redirecting "not found" requests to home, which itself redirects to index.html + - providing the endpoint /config.json, which the front-end uses to know + what are the API and websocket prefixes +""" + +import re +from pathlib import Path +from typing import Any, Optional, Sequence + +from fastapi import FastAPI +from pydantic import BaseModel +from starlette.middleware.base import BaseHTTPMiddleware, DispatchFunction, RequestResponseEndpoint +from starlette.requests import Request +from starlette.responses import FileResponse +from starlette.staticfiles import StaticFiles +from starlette.types import ASGIApp + +from antarest.core.utils.string import to_camel_case + + +class RedirectMiddleware(BaseHTTPMiddleware): + """ + Middleware that rewrites the URL path to "/" for incoming requests + that do not match the known end points. This is useful for redirecting requests + to the main page of a ReactJS application when the user refreshes the browser. + """ + + def __init__( + self, + app: ASGIApp, + dispatch: Optional[DispatchFunction] = None, + route_paths: Sequence[str] = (), + ) -> None: + """ + Initializes an instance of the URLRewriterMiddleware. + + Args: + app: The ASGI application to which the middleware is applied. + dispatch: The dispatch function to use. + route_paths: The known route paths of the application. + Requests that do not match any of these paths will be rewritten to the root path. + + Note: + The `route_paths` should contain all the known endpoints of the application. + """ + dispatch = self.dispatch if dispatch is None else dispatch + super().__init__(app, dispatch) + self.known_prefixes = {re.findall(r"/(?:(?!/).)*", p)[0] for p in route_paths if p != "/"} + + async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Any: + """ + Intercepts the incoming request and rewrites the URL path if necessary. + Passes the modified or original request to the next middleware or endpoint handler. + """ + url_path = request.scope["path"] + if url_path in {"", "/"}: + pass + elif not any(url_path.startswith(ep) for ep in self.known_prefixes): + request.scope["path"] = "/" + return await call_next(request) + + +class BackEndConfig(BaseModel): + """ + Configuration about backend URLs served to the frontend. + """ + + rest_endpoint: str + ws_endpoint: str + + class Config: + populate_by_name = True + alias_generator = to_camel_case + + +def create_backend_config(api_prefix: str) -> BackEndConfig: + if not api_prefix.startswith("/"): + api_prefix = "/" + api_prefix + return BackEndConfig(rest_endpoint=f"{api_prefix}", ws_endpoint=f"{api_prefix}/ws") + + +def add_front_app(application: FastAPI, resources_dir: Path, api_prefix: str) -> None: + """ + This functions adds the logic necessary to serve both + the front-end application and the backend HTTP application. + + This includes: + - serving static frontend files + - redirecting "not found" requests to home, which itself redirects to index.html + - providing the endpoint /config.json, which the front-end uses to know + what are the API and websocket prefixes + """ + backend_config = create_backend_config(api_prefix) + + front_app_dir = resources_dir / "webapp" + + # Serve front-end files + application.mount( + "/static", + StaticFiles(directory=front_app_dir), + name="static", + ) + + # Redirect home to index.html + @application.get("/", include_in_schema=False) + def home(request: Request) -> Any: + return FileResponse(front_app_dir / "index.html", 200) + + # Serve config for the front-end at /config.json + @application.get("/config.json", include_in_schema=False) + def get_api_paths_config(request: Request) -> BackEndConfig: + return backend_config + + # When the web application is running in Desktop mode, the ReactJS web app + # is served at the `/static` entry point. Any requests that are not API + # requests should be redirected to the `index.html` file, which will handle + # the route provided by the URL. + route_paths = [r.path for r in application.routes] # type: ignore + application.add_middleware( + RedirectMiddleware, + route_paths=route_paths, + ) diff --git a/antarest/gui.py b/antarest/gui.py index 399b0a2518..f36904a060 100644 --- a/antarest/gui.py +++ b/antarest/gui.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import multiprocessing import platform @@ -6,16 +18,8 @@ from multiprocessing import Process from pathlib import Path -try: - # `httpx` is a modern alternative to the `requests` library - import httpx as requests - from httpx import ConnectError as ConnectionError -except ImportError: - # noinspection PyUnresolvedReferences, PyPackageRequirements - import requests - from requests import ConnectionError - -import uvicorn # type: ignore +import httpx +import uvicorn from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QAction, QApplication, QMenu, QSystemTrayIcon @@ -90,8 +94,8 @@ def main() -> None: ) server.start() for _ in range(30, 0, -1): - with contextlib.suppress(ConnectionError): - res = requests.get("http://localhost:8080") + with contextlib.suppress(httpx.ConnectError): + res = httpx.get("http://localhost:8080") if res.status_code == 200: break time.sleep(1) diff --git a/antarest/launcher/__init__.py b/antarest/launcher/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/launcher/__init__.py +++ b/antarest/launcher/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/launcher/adapters/__init__.py b/antarest/launcher/adapters/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/launcher/adapters/__init__.py +++ b/antarest/launcher/adapters/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/launcher/adapters/abstractlauncher.py b/antarest/launcher/adapters/abstractlauncher.py index 121f952899..4b845f8de0 100644 --- a/antarest/launcher/adapters/abstractlauncher.py +++ b/antarest/launcher/adapters/abstractlauncher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os from abc import ABC, abstractmethod from pathlib import Path @@ -88,7 +100,7 @@ def update_log(log_line: str) -> None: ) launch_progress_json = self.cache.get(id=f"Launch_Progress_{job_id}") or {} - launch_progress_dto = LaunchProgressDTO.parse_obj(launch_progress_json) + launch_progress_dto = LaunchProgressDTO.model_validate(launch_progress_json) if launch_progress_dto.parse_log_lines(log_line.splitlines()): self.event_bus.push( Event( @@ -102,6 +114,6 @@ def update_log(log_line: str) -> None: channel=EventChannelDirectory.JOB_STATUS + job_id, ) ) - self.cache.put(f"Launch_Progress_{job_id}", launch_progress_dto.dict()) + self.cache.put(f"Launch_Progress_{job_id}", launch_progress_dto.model_dump()) return update_log diff --git a/antarest/launcher/adapters/factory_launcher.py b/antarest/launcher/adapters/factory_launcher.py index 1ff1944635..a7b3fcfdd2 100644 --- a/antarest/launcher/adapters/factory_launcher.py +++ b/antarest/launcher/adapters/factory_launcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import Dict diff --git a/antarest/launcher/adapters/local_launcher/__init__.py b/antarest/launcher/adapters/local_launcher/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/launcher/adapters/local_launcher/__init__.py +++ b/antarest/launcher/adapters/local_launcher/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/launcher/adapters/local_launcher/local_launcher.py b/antarest/launcher/adapters/local_launcher/local_launcher.py index 8ee598985b..4db8beb5ae 100644 --- a/antarest/launcher/adapters/local_launcher/local_launcher.py +++ b/antarest/launcher/adapters/local_launcher/local_launcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import logging import shutil diff --git a/antarest/launcher/adapters/log_manager.py b/antarest/launcher/adapters/log_manager.py index eeca586f32..f85810f1ae 100644 --- a/antarest/launcher/adapters/log_manager.py +++ b/antarest/launcher/adapters/log_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import io import logging diff --git a/antarest/launcher/adapters/log_parser.py b/antarest/launcher/adapters/log_parser.py index 0605e8fced..efd73d1b70 100644 --- a/antarest/launcher/adapters/log_parser.py +++ b/antarest/launcher/adapters/log_parser.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import functools import re import typing as t diff --git a/antarest/launcher/adapters/slurm_launcher/__init__.py b/antarest/launcher/adapters/slurm_launcher/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/launcher/adapters/slurm_launcher/__init__.py +++ b/antarest/launcher/adapters/slurm_launcher/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py b/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py index 92e2755408..74132b89f0 100644 --- a/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py +++ b/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import argparse import logging import os diff --git a/antarest/launcher/extensions/__init__.py b/antarest/launcher/extensions/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/launcher/extensions/__init__.py +++ b/antarest/launcher/extensions/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/launcher/extensions/adequacy_patch/__init__.py b/antarest/launcher/extensions/adequacy_patch/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/launcher/extensions/adequacy_patch/__init__.py +++ b/antarest/launcher/extensions/adequacy_patch/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/launcher/extensions/adequacy_patch/extension.py b/antarest/launcher/extensions/adequacy_patch/extension.py index d6499375e8..20cd3407cd 100644 --- a/antarest/launcher/extensions/adequacy_patch/extension.py +++ b/antarest/launcher/extensions/adequacy_patch/extension.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import shutil from pathlib import Path diff --git a/antarest/launcher/extensions/interface.py b/antarest/launcher/extensions/interface.py index 5401a2a6ae..c7a3b3c39a 100644 --- a/antarest/launcher/extensions/interface.py +++ b/antarest/launcher/extensions/interface.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from abc import ABC, abstractmethod from pathlib import Path from typing import Any diff --git a/antarest/launcher/main.py b/antarest/launcher/main.py index 5f47bfe467..1916b9607b 100644 --- a/antarest/launcher/main.py +++ b/antarest/launcher/main.py @@ -1,7 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.filetransfer.service import FileTransferManager from antarest.core.interfaces.cache import ICache @@ -14,7 +27,7 @@ def build_launcher( - application: Optional[FastAPI], + app_ctxt: Optional[AppBuildContext], config: Config, study_service: StudyService, file_transfer_manager: FileTransferManager, @@ -37,7 +50,7 @@ def build_launcher( cache=cache, ) - if service_launcher and application: - application.include_router(create_launcher_api(service_launcher, config)) + if service_launcher and app_ctxt: + app_ctxt.api_root.include_router(create_launcher_api(service_launcher, config)) return service_launcher diff --git a/antarest/launcher/model.py b/antarest/launcher/model.py index 3bd3427a07..d80400a4ba 100644 --- a/antarest/launcher/model.py +++ b/antarest/launcher/model.py @@ -1,5 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import enum -import json import typing as t from datetime import datetime @@ -8,12 +19,13 @@ from sqlalchemy.orm import relationship # type: ignore from antarest.core.persistence import Base -from antarest.core.utils.string import to_camel_case +from antarest.core.serialization import from_json from antarest.login.model import Identity, UserInfo +from antarest.study.business.all_optional_meta import camel_case_model class XpansionParametersDTO(BaseModel): - output_id: t.Optional[str] + output_id: t.Optional[str] = None sensitivity_mode: bool = False enabled: bool = True @@ -42,7 +54,7 @@ def from_launcher_params(cls, params: t.Optional[str]) -> "LauncherParametersDTO """ if params is None: return cls() - return cls.parse_obj(json.loads(params)) + return cls.model_validate(from_json(params)) class LogType(str, enum.Enum): @@ -113,7 +125,7 @@ class JobResultDTO(BaseModel): class Config: @staticmethod - def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: + def json_schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: schema["example"] = JobResultDTO( id="b2a9f6a7-7f8f-4f7a-9a8b-1f9b4c5d6e7f", study_id="b2a9f6a7-7f8f-4f7a-9a8b-1f9b4c5d6e7f", @@ -127,7 +139,7 @@ def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: exit_code=0, solver_stats="time: 1651s, call_count: 1, optimization_issues: []", owner=UserInfo(id=0o007, name="James BOND"), - ) + ).model_dump() class JobLog(Base): # type: ignore @@ -228,13 +240,8 @@ class LauncherEnginesDTO(BaseModel): engines: t.List[str] -class LauncherLoadDTO( - BaseModel, - extra="forbid", - validate_assignment=True, - allow_population_by_field_name=True, - alias_generator=to_camel_case, -): +@camel_case_model +class LauncherLoadDTO(BaseModel, extra="forbid", validate_assignment=True, populate_by_name=True): """ DTO representing the load of the SLURM cluster or local machine. diff --git a/antarest/launcher/repository.py b/antarest/launcher/repository.py index e6ad782a38..21126aac1d 100644 --- a/antarest/launcher/repository.py +++ b/antarest/launcher/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Optional diff --git a/antarest/launcher/service.py b/antarest/launcher/service.py index 8c8e88905d..2dad1aef00 100644 --- a/antarest/launcher/service.py +++ b/antarest/launcher/service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import functools import logging import os @@ -10,7 +22,7 @@ from fastapi import HTTPException -from antarest.core.config import Config, NbCoresConfig +from antarest.core.config import Config, Launcher, NbCoresConfig from antarest.core.exceptions import StudyNotFoundError from antarest.core.filetransfer.model import FileDownloadTaskDTO from antarest.core.filetransfer.service import FileTransferManager @@ -102,7 +114,7 @@ def _init_extensions(self) -> Dict[str, ILauncherExtension]: def get_launchers(self) -> List[str]: return list(self.launchers.keys()) - def get_nb_cores(self, launcher: str) -> NbCoresConfig: + def get_nb_cores(self, launcher: Launcher) -> NbCoresConfig: """ Retrieve the configuration of the launcher's nb of cores. @@ -111,9 +123,6 @@ def get_nb_cores(self, launcher: str) -> NbCoresConfig: Returns: Number of cores of the launcher - - Raises: - InvalidConfigurationError: if the launcher configuration is not available """ return self.config.launcher.get_nb_cores(launcher) @@ -174,7 +183,7 @@ def update( self.event_bus.push( Event( type=EventType.STUDY_JOB_COMPLETED if final_status else EventType.STUDY_JOB_STATUS_UPDATE, - payload=job_result.to_dto().dict(), + payload=job_result.to_dto().model_dump(), permissions=PermissionInfo(public_mode=PublicMode.READ), channel=EventChannelDirectory.JOB_STATUS + job_result.id, ) @@ -235,7 +244,7 @@ def run_study( study_id=study_uuid, job_status=JobStatus.PENDING, launcher=launcher, - launcher_params=launcher_parameters.json() if launcher_parameters else None, + launcher_params=launcher_parameters.model_dump_json() if launcher_parameters else None, owner_id=(owner_id or None), ) self.job_result_repository.save(job_status) @@ -251,7 +260,7 @@ def run_study( self.event_bus.push( Event( type=EventType.STUDY_JOB_STARTED, - payload=job_status.to_dto().dict(), + payload=job_status.to_dto().model_dump(), permissions=PermissionInfo.from_study(study_info), ) ) @@ -292,7 +301,7 @@ def kill_job(self, job_id: str, params: RequestParameters) -> JobResult: self.event_bus.push( Event( type=EventType.STUDY_JOB_CANCELLED, - payload=job_status.to_dto().dict(), + payload=job_status.to_dto().model_dump(), permissions=PermissionInfo.from_study(study), channel=EventChannelDirectory.JOB_STATUS + job_result.id, ) @@ -706,5 +715,7 @@ def get_launch_progress(self, job_id: str, params: RequestParameters) -> float: if launcher is None: raise ValueError(f"Job {job_id} has no launcher") - launch_progress_json = self.launchers[launcher].cache.get(id=f"Launch_Progress_{job_id}") or {"progress": 0} + launch_progress_json: Dict[str, float] = self.launchers[launcher].cache.get(id=f"Launch_Progress_{job_id}") or { + "progress": 0 + } return launch_progress_json.get("progress", 0) diff --git a/antarest/launcher/ssh_client.py b/antarest/launcher/ssh_client.py index e52cb0072c..175c8a739b 100644 --- a/antarest/launcher/ssh_client.py +++ b/antarest/launcher/ssh_client.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import shlex import socket @@ -31,7 +43,7 @@ class SlurmError(Exception): def execute_command(ssh_config: SSHConfigDTO, args: List[str]) -> Any: command = " ".join(args) try: - with ssh_client(ssh_config) as client: # type: ignore + with ssh_client(ssh_config) as client: # type: paramiko.SSHClient _, stdout, stderr = client.exec_command(command, timeout=10) output = stdout.read().decode("utf-8").strip() error = stderr.read().decode("utf-8").strip() diff --git a/antarest/launcher/ssh_config.py b/antarest/launcher/ssh_config.py index 1fa4a4393c..5238e07608 100644 --- a/antarest/launcher/ssh_config.py +++ b/antarest/launcher/ssh_config.py @@ -1,8 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import pathlib from typing import Any, Dict, Optional import paramiko -from pydantic import BaseModel, root_validator +from pydantic import BaseModel, model_validator class SSHConfigDTO(BaseModel): @@ -14,7 +26,7 @@ class SSHConfigDTO(BaseModel): key_password: Optional[str] = "" password: Optional[str] = "" - @root_validator() + @model_validator(mode="before") def validate_connection_information(cls, values: Dict[str, Any]) -> Dict[str, Any]: if "private_key_file" not in values and "password" not in values: raise paramiko.AuthenticationException("SSH config needs at least a private key or a password") diff --git a/antarest/launcher/web.py b/antarest/launcher/web.py index 9635c664f1..c07261384a 100644 --- a/antarest/launcher/web.py +++ b/antarest/launcher/web.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http import logging from typing import Any, Dict, List, Optional @@ -6,7 +18,7 @@ from fastapi import APIRouter, Depends, Query from fastapi.exceptions import HTTPException -from antarest.core.config import Config, InvalidConfigurationError +from antarest.core.config import Config, InvalidConfigurationError, Launcher from antarest.core.filetransfer.model import FileDownloadTaskDTO from antarest.core.jwt import JWTUser from antarest.core.requests import RequestParameters @@ -42,8 +54,8 @@ def __init__(self, solver: str) -> None: LauncherQuery = Query( - "default", - examples={ + default=Launcher.DEFAULT, + openapi_examples={ "Default launcher": { "description": "Default solver (auto-detected)", "value": "default", @@ -233,7 +245,7 @@ def get_load() -> LauncherLoadDTO: summary="Get list of supported solver versions", response_model=List[str], ) - def get_solver_versions(solver: str = LauncherQuery) -> List[str]: + def get_solver_versions(solver: Launcher = Launcher.DEFAULT) -> List[str]: """ Get list of supported solver versions defined in the configuration. @@ -241,8 +253,6 @@ def get_solver_versions(solver: str = LauncherQuery) -> List[str]: - `solver`: name of the configuration to read: "default", "slurm" or "local". """ logger.info(f"Fetching the list of solver versions for the '{solver}' configuration") - if solver not in {"default", "slurm", "local"}: - raise UnknownSolverConfig(solver) return service.get_solver_versions(solver) # noinspection SpellCheckingInspection @@ -252,7 +262,7 @@ def get_solver_versions(solver: str = LauncherQuery) -> List[str]: summary="Retrieving Min, Default, and Max Core Count", response_model=Dict[str, int], ) - def get_nb_cores(launcher: str = LauncherQuery) -> Dict[str, int]: + def get_nb_cores(launcher: Launcher = Launcher.DEFAULT) -> Dict[str, int]: """ Retrieve the numer of cores of the launcher. @@ -277,7 +287,7 @@ def get_nb_cores(launcher: str = LauncherQuery) -> Dict[str, int]: tags=[APITag.launcher], summary="Retrieve the time limit for a job (in hours)", ) - def get_time_limit(launcher: str = LauncherQuery) -> Dict[str, int]: + def get_time_limit(launcher: Launcher = LauncherQuery) -> Dict[str, int]: """ Retrieve the time limit for a job (in hours) of the given launcher: "local" or "slurm". diff --git a/antarest/login/__init__.py b/antarest/login/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/login/__init__.py +++ b/antarest/login/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/login/auth.py b/antarest/login/auth.py index cc7638b728..f86ca5903b 100644 --- a/antarest/login/auth.py +++ b/antarest/login/auth.py @@ -1,16 +1,28 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from datetime import timedelta from typing import Any, Callable, Coroutine, Dict, Optional, Tuple, Union from fastapi import Depends -from fastapi_jwt_auth import AuthJWT # type: ignore from pydantic import BaseModel from ratelimit.types import Scope # type: ignore from starlette.requests import Request from antarest.core.config import Config from antarest.core.jwt import DEFAULT_ADMIN_USER, JWTUser +from antarest.core.serialization import from_json +from antarest.fastapi_jwt_auth import AuthJWT logger = logging.getLogger(__name__) @@ -54,14 +66,14 @@ def get_current_user(self, auth_jwt: AuthJWT = Depends()) -> JWTUser: auth_jwt.jwt_required() - user = JWTUser.parse_obj(json.loads(auth_jwt.get_jwt_subject())) + user = JWTUser.model_validate(from_json(auth_jwt.get_jwt_subject())) return user @staticmethod def get_user_from_token(token: str, jwt_manager: AuthJWT) -> Optional[JWTUser]: try: token_data = jwt_manager._verified_token(token) - return JWTUser.parse_obj(json.loads(token_data["sub"])) + return JWTUser.model_validate(from_json(token_data["sub"])) except Exception as e: logger.debug("Failed to retrieve user from token", exc_info=e) return None diff --git a/antarest/login/ldap.py b/antarest/login/ldap.py index d558238288..1635efe09d 100644 --- a/antarest/login/ldap.py +++ b/antarest/login/ldap.py @@ -1,13 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from dataclasses import dataclass from typing import Dict, List, Optional -try: - # `httpx` is a modern alternative to the `requests` library - import httpx as requests -except ImportError: - # noinspection PyUnresolvedReferences, PyPackageRequirements - import requests +import httpx from antarest.core.config import Config from antarest.core.model import JSON @@ -98,7 +105,7 @@ def _fetch(self, name: str, password: str) -> Optional[ExternalUser]: auth = AuthDTO(user=name, password=password) try: - res = requests.post(url=f"{self.url}/auth", json=auth.to_json()) + res = httpx.post(url=f"{self.url}/auth", json=auth.to_json()) except Exception as e: logger.warning( "Failed to retrieve user from external auth service", diff --git a/antarest/login/main.py b/antarest/login/main.py index d87a082abd..ac6b2956c9 100644 --- a/antarest/login/main.py +++ b/antarest/login/main.py @@ -1,16 +1,28 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus from typing import Any, Optional -from fastapi import FastAPI -from fastapi_jwt_auth import AuthJWT # type: ignore -from fastapi_jwt_auth.exceptions import AuthJWTException # type: ignore from starlette.requests import Request from starlette.responses import JSONResponse +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.interfaces.eventbus import DummyEventBusService, IEventBus +from antarest.core.serialization import from_json from antarest.core.utils.fastapi_sqlalchemy import db +from antarest.fastapi_jwt_auth import AuthJWT +from antarest.fastapi_jwt_auth.exceptions import AuthJWTException from antarest.login.ldap import LdapService from antarest.login.repository import BotRepository, GroupRepository, RoleRepository, UserLdapRepository, UserRepository from antarest.login.service import LoginService @@ -18,7 +30,7 @@ def build_login( - application: Optional[FastAPI], + app_ctxt: Optional[AppBuildContext], config: Config, service: Optional[LoginService] = None, event_bus: IEventBus = DummyEventBusService(), @@ -27,7 +39,7 @@ def build_login( Login module linking dependency Args: - application: flask application + app_ctxt: application config: server configuration service: used by testing to inject mock. Let None to use true instantiation event_bus: used by testing to inject mock. Let None to use true instantiation @@ -54,9 +66,9 @@ def build_login( event_bus=event_bus, ) - if application: + if app_ctxt: - @application.exception_handler(AuthJWTException) + @app_ctxt.app.exception_handler(AuthJWTException) def authjwt_exception_handler(request: Request, exc: AuthJWTException) -> Any: return JSONResponse( status_code=HTTPStatus.UNAUTHORIZED, @@ -65,12 +77,12 @@ def authjwt_exception_handler(request: Request, exc: AuthJWTException) -> Any: @AuthJWT.token_in_denylist_loader # type: ignore def check_if_token_is_revoked(decrypted_token: Any) -> bool: - subject = json.loads(decrypted_token["sub"]) + subject = from_json(decrypted_token["sub"]) user_id = subject["id"] token_type = subject["type"] with db(): return token_type == "bots" and service is not None and not service.exists_bot(user_id) - if application: - application.include_router(create_login_api(service, config)) + if app_ctxt: + app_ctxt.api_root.include_router(create_login_api(service, config)) return service diff --git a/antarest/login/model.py b/antarest/login/model.py index 097de6d75e..4f85763c9b 100644 --- a/antarest/login/model.py +++ b/antarest/login/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import typing as t import uuid diff --git a/antarest/login/repository.py b/antarest/login/repository.py index d70fa57e13..d37c75a30d 100644 --- a/antarest/login/repository.py +++ b/antarest/login/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Optional diff --git a/antarest/login/service.py b/antarest/login/service.py index 55af0ab12c..d3103a6dfc 100644 --- a/antarest/login/service.py +++ b/antarest/login/service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Optional, Union @@ -473,7 +485,7 @@ def authenticate(self, name: str, pwd: str) -> Optional[JWTUser]: """ intern: Optional[User] = self.users.get_by_name(name) - if intern and intern.password.check(pwd): # type: ignore + if intern and intern.password.check(pwd): logger.info("successful login from intern user %s", name) return self.get_jwt(intern.id) diff --git a/antarest/login/web.py b/antarest/login/web.py index 801325df7c..5bc85c62a1 100644 --- a/antarest/login/web.py +++ b/antarest/login/web.py @@ -1,10 +1,20 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from datetime import timedelta from typing import Any, List, Optional, Union from fastapi import APIRouter, Depends, HTTPException -from fastapi_jwt_auth import AuthJWT # type: ignore from markupsafe import escape from pydantic import BaseModel @@ -12,7 +22,9 @@ from antarest.core.jwt import JWTGroup, JWTUser from antarest.core.requests import RequestParameters, UserHasNotPermissionError from antarest.core.roles import RoleType +from antarest.core.serialization import from_json from antarest.core.utils.web import APITag +from antarest.fastapi_jwt_auth import AuthJWT from antarest.login.auth import Auth from antarest.login.model import ( BotCreateDTO, @@ -55,8 +67,8 @@ def create_login_api(service: LoginService, config: Config) -> APIRouter: auth = Auth(config) def generate_tokens(user: JWTUser, jwt_manager: AuthJWT, expire: Optional[timedelta] = None) -> CredentialsDTO: - access_token = jwt_manager.create_access_token(subject=user.json(), expires_time=expire) - refresh_token = jwt_manager.create_refresh_token(subject=user.json()) + access_token = jwt_manager.create_access_token(subject=user.model_dump_json(), expires_time=expire) + refresh_token = jwt_manager.create_refresh_token(subject=user.model_dump_json()) return CredentialsDTO( user=user.id, access_token=access_token.decode() if isinstance(access_token, bytes) else access_token, @@ -91,7 +103,7 @@ def login( ) def refresh(jwt_manager: AuthJWT = Depends()) -> Any: jwt_manager.jwt_refresh_token_required() - identity = json.loads(jwt_manager.get_jwt_subject()) + identity = from_json(jwt_manager.get_jwt_subject()) logger.debug(f"Refreshing access token for {identity['id']}") user = service.get_jwt(identity["id"]) if user: @@ -114,11 +126,7 @@ def users_get_all( params = RequestParameters(user=current_user) return service.get_all_users(params, details) - @bp.get( - "/users/{id}", - tags=[APITag.users], - response_model=Union[IdentityDTO, UserInfo], # type: ignore - ) + @bp.get("/users/{id}", tags=[APITag.users], response_model=Union[IdentityDTO, UserInfo]) def users_get_id( id: int, details: bool = False, @@ -192,11 +200,7 @@ def groups_get_all( params = RequestParameters(user=current_user) return service.get_all_groups(params, details) - @bp.get( - "/groups/{id}", - tags=[APITag.users], - response_model=Union[GroupDetailDTO, GroupDTO], # type: ignore - ) + @bp.get("/groups/{id}", tags=[APITag.users], response_model=Union[GroupDetailDTO, GroupDTO]) def groups_get_id( id: str, details: bool = False, @@ -314,11 +318,7 @@ def bots_create( tokens = generate_tokens(jwt, jwt_manager, expire=timedelta(days=368 * 200)) return tokens.access_token - @bp.get( - "/bots/{id}", - tags=[APITag.users], - response_model=Union[BotIdentityDTO, BotDTO], # type: ignore - ) + @bp.get("/bots/{id}", tags=[APITag.users], response_model=Union[BotIdentityDTO, BotDTO]) def get_bot( id: int, verbose: Optional[int] = None, diff --git a/antarest/main.py b/antarest/main.py index 3973c79ace..e521124447 100644 --- a/antarest/main.py +++ b/antarest/main.py @@ -1,29 +1,37 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import argparse import copy import logging -import re +from contextlib import asynccontextmanager from pathlib import Path -from typing import Any, Dict, Optional, Sequence, Tuple, cast +from typing import Any, AsyncGenerator, Dict, Optional, Tuple, cast import pydantic -import uvicorn # type: ignore -import uvicorn.config # type: ignore -from fastapi import FastAPI, HTTPException +import uvicorn +import uvicorn.config +from fastapi import APIRouter, FastAPI, HTTPException from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError -from fastapi_jwt_auth import AuthJWT # type: ignore from ratelimit import RateLimitMiddleware # type: ignore from ratelimit.backends.redis import RedisBackend # type: ignore from ratelimit.backends.simple import MemoryBackend # type: ignore -from starlette.middleware.base import BaseHTTPMiddleware, DispatchFunction, RequestResponseEndpoint from starlette.middleware.cors import CORSMiddleware from starlette.requests import Request from starlette.responses import JSONResponse -from starlette.staticfiles import StaticFiles -from starlette.templating import Jinja2Templates -from starlette.types import ASGIApp from antarest import __version__ +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.core_blueprint import create_utils_routes from antarest.core.filesystem_blueprint import create_file_system_blueprint @@ -34,14 +42,16 @@ from antarest.core.utils.fastapi_sqlalchemy import DBSessionMiddleware from antarest.core.utils.utils import get_local_path from antarest.core.utils.web import tags_metadata +from antarest.fastapi_jwt_auth import AuthJWT +from antarest.front import add_front_app from antarest.login.auth import Auth, JwtSettings from antarest.login.model import init_admin_user from antarest.matrixstore.matrix_garbage_collector import MatrixGarbageCollector +from antarest.service_creator import SESSION_ARGS, Module, create_services, init_db_engine from antarest.singleton_services import start_all_services from antarest.study.storage.auto_archive_service import AutoArchiveService from antarest.study.storage.rawstudy.watcher import Watcher from antarest.tools.admin_lib import clean_locks -from antarest.utils import SESSION_ARGS, Module, create_services, init_db_engine logger = logging.getLogger(__name__) @@ -177,55 +187,6 @@ def parse_arguments() -> argparse.Namespace: return parser.parse_args() -class URLRewriterMiddleware(BaseHTTPMiddleware): - """ - Middleware that rewrites the URL path to "/" (root path) for incoming requests - that do not match the known end points. This is useful for redirecting requests - to the main page of a ReactJS application when the user refreshes the browser. - """ - - def __init__( - self, - app: ASGIApp, - dispatch: Optional[DispatchFunction] = None, - root_path: str = "", - route_paths: Sequence[str] = (), - ) -> None: - """ - Initializes an instance of the URLRewriterMiddleware. - - Args: - app: The ASGI application to which the middleware is applied. - dispatch: The dispatch function to use. - root_path: The root path of the application. - The URL path will be rewritten relative to this root path. - route_paths: The known route paths of the application. - Requests that do not match any of these paths will be rewritten to the root path. - - Note: - The `root_path` can be set to a specific component of the URL path, such as "api". - The `route_paths` should contain all the known endpoints of the application. - """ - dispatch = self.dispatch if dispatch is None else dispatch - super().__init__(app, dispatch) - self.root_path = f"/{root_path}" if root_path else "" - self.known_prefixes = {re.findall(r"/(?:(?!/).)*", p)[0] for p in route_paths if p != "/"} - - async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Any: - """ - Intercepts the incoming request and rewrites the URL path if necessary. - Passes the modified or original request to the next middleware or endpoint handler. - """ - url_path = request.scope["path"] - if url_path in {"", "/"}: - pass - elif self.root_path and url_path.startswith(self.root_path): - request.scope["path"] = url_path[len(self.root_path) :] - elif not any(url_path.startswith(ep) for ep in self.known_prefixes): - request.scope["path"] = "/" - return await call_next(request) - - def fastapi_app( config_file: Path, resource_path: Optional[Path] = None, @@ -238,46 +199,39 @@ def fastapi_app( logger.info("Initiating application") + @asynccontextmanager + async def set_default_executor(app: FastAPI) -> AsyncGenerator[None, None]: + import asyncio + from concurrent.futures import ThreadPoolExecutor + + loop = asyncio.get_running_loop() + loop.set_default_executor(ThreadPoolExecutor(max_workers=config.server.worker_threadpool_size)) + yield + application = FastAPI( title="AntaREST", version=__version__, docs_url=None, root_path=config.root_path, openapi_tags=tags_metadata, + lifespan=set_default_executor, + openapi_url=f"{config.api_prefix}/openapi.json", ) + api_root = APIRouter(prefix=config.api_prefix) + + app_ctxt = AppBuildContext(application, api_root) + # Database engine = init_db_engine(config_file, config, auto_upgrade_db) application.add_middleware(DBSessionMiddleware, custom_engine=engine, session_args=SESSION_ARGS) + # Since Starlette Version 0.24.0, the middlewares are lazily build inside this function + # But we need to instantiate this middleware as it's needed for the study service. + # So we manually instantiate it here. + DBSessionMiddleware(None, custom_engine=engine, session_args=cast(Dict[str, bool], SESSION_ARGS)) application.add_middleware(LoggingMiddleware) - if mount_front: - application.mount( - "/static", - StaticFiles(directory=str(res / "webapp")), - name="static", - ) - templates = Jinja2Templates(directory=str(res / "templates")) - - @application.get("/", include_in_schema=False) - def home(request: Request) -> Any: - return templates.TemplateResponse("index.html", {"request": request}) - - else: - # noinspection PyUnusedLocal - @application.get("/", include_in_schema=False) - def home(request: Request) -> Any: - return "" - - @application.on_event("startup") - def set_default_executor() -> None: - import asyncio - from concurrent.futures import ThreadPoolExecutor - - loop = asyncio.get_running_loop() - loop.set_default_executor(ThreadPoolExecutor(max_workers=config.server.worker_threadpool_size)) - # TODO move that elsewhere @AuthJWT.load_config # type: ignore def get_config() -> JwtSettings: @@ -296,8 +250,8 @@ def get_config() -> JwtSettings: allow_methods=["*"], allow_headers=["*"], ) - application.include_router(create_utils_routes(config)) - application.include_router(create_file_system_blueprint(config)) + api_root.include_router(create_utils_routes(config)) + api_root.include_router(create_file_system_blueprint(config)) # noinspection PyUnusedLocal @application.exception_handler(HTTPException) @@ -407,19 +361,9 @@ def handle_all_exception(request: Request, exc: Exception) -> Any: ) init_admin_user(engine=engine, session_args=SESSION_ARGS, admin_password=config.security.admin_pwd) - services = create_services(config, application) + services = create_services(config, app_ctxt) - if mount_front: - # When the web application is running in Desktop mode, the ReactJS web app - # is served at the `/static` entry point. Any requests that are not API - # requests should be redirected to the `index.html` file, which will handle - # the route provided by the URL. - route_paths = [r.path for r in application.routes] # type: ignore - application.add_middleware( - URLRewriterMiddleware, - root_path=application.root_path, - route_paths=route_paths, - ) + application.include_router(api_root) if config.server.services and Module.WATCHER.value in config.server.services: watcher = cast(Watcher, services["watcher"]) @@ -434,6 +378,15 @@ def handle_all_exception(request: Request, exc: Exception) -> Any: auto_archiver.start() customize_openapi(application) + + if mount_front: + add_front_app(application, res, config.api_prefix) + else: + # noinspection PyUnusedLocal + @application.get("/", include_in_schema=False) + def home(request: Request) -> Any: + return "" + cancel_orphan_tasks(engine=engine, session_args=SESSION_ARGS) return application, services diff --git a/antarest/matrixstore/__init__.py b/antarest/matrixstore/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/matrixstore/__init__.py +++ b/antarest/matrixstore/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/matrixstore/exceptions.py b/antarest/matrixstore/exceptions.py index 305cf0539c..9f9051ca4d 100644 --- a/antarest/matrixstore/exceptions.py +++ b/antarest/matrixstore/exceptions.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus from fastapi import HTTPException diff --git a/antarest/matrixstore/main.py b/antarest/matrixstore/main.py index b59e3eb87a..d8eaf0390a 100644 --- a/antarest/matrixstore/main.py +++ b/antarest/matrixstore/main.py @@ -1,7 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.filetransfer.service import FileTransferManager from antarest.core.tasks.service import ITaskService @@ -12,7 +25,7 @@ def build_matrix_service( - application: Optional[FastAPI], + app_ctxt: Optional[AppBuildContext], config: Config, file_transfer_manager: FileTransferManager, task_service: ITaskService, @@ -23,7 +36,7 @@ def build_matrix_service( Matrix module linking dependency Args: - application: flask application + app_ctxt: application config: server configuration file_transfer_manager: File transfer manager task_service: Task manager @@ -48,7 +61,7 @@ def build_matrix_service( config=config, ) - if application: - application.include_router(create_matrix_api(service, file_transfer_manager, config)) + if app_ctxt: + app_ctxt.api_root.include_router(create_matrix_api(service, file_transfer_manager, config)) return service diff --git a/antarest/matrixstore/matrix_editor.py b/antarest/matrixstore/matrix_editor.py index ffaf619322..838af83860 100644 --- a/antarest/matrixstore/matrix_editor.py +++ b/antarest/matrixstore/matrix_editor.py @@ -1,8 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import functools import operator from typing import Any, Dict, List, Optional, Tuple -from pydantic import BaseModel, Extra, Field, root_validator, validator +from pydantic import BaseModel, Field, field_validator, model_validator class MatrixSlice(BaseModel): @@ -23,8 +35,8 @@ class MatrixSlice(BaseModel): column_to: int class Config: - extra = Extra.forbid - schema_extra = { + extra = "forbid" + json_schema_extra = { "example": { "column_from": 5, "column_to": 8, @@ -33,7 +45,7 @@ class Config: } } - @root_validator(pre=True) + @model_validator(mode="before") def check_values(cls, values: Dict[str, Any]) -> Dict[str, Any]: """ Converts and validates the slice coordinates. @@ -95,12 +107,12 @@ class Operation(BaseModel): - `value`: The value associated with the operation. """ - operation: str = Field(regex=r"[=/*+-]|ABS") + operation: str = Field(pattern=r"[=/*+-]|ABS") value: float class Config: - extra = Extra.forbid - schema_extra = {"example": {"operation": "=", "value": 120.0}} + extra = "forbid" + json_schema_extra = {"example": {"operation": "=", "value": 120.0}} # noinspection SpellCheckingInspection def compute(self, x: Any, use_coords: bool = False) -> Any: @@ -145,16 +157,17 @@ class MatrixEditInstruction(BaseModel): operation: Operation class Config: - extra = Extra.forbid - - @staticmethod - def schema_extra(schema: Dict[str, Any]) -> None: - schema["example"] = MatrixEditInstruction( - coordinates=[(0, 10), (0, 11), (0, 12)], - operation=Operation(operation="=", value=120.0), - ) + extra = "forbid" + json_schema_extra = { + "example": { + "column_from": 5, + "column_to": 8, + "row_from": 0, + "row_to": 8760, + } + } - @root_validator(pre=True) + @model_validator(mode="before") def check_slice_coordinates(cls, values: Dict[str, Any]) -> Dict[str, Any]: """ Validates the 'slices' and 'coordinates' fields. @@ -179,7 +192,7 @@ def check_slice_coordinates(cls, values: Dict[str, Any]) -> Dict[str, Any]: return values - @validator("coordinates") + @field_validator("coordinates") def validate_coordinates(cls, coordinates: Optional[List[Tuple[int, int]]]) -> Optional[List[Tuple[int, int]]]: """ Validates the `coordinates` field. diff --git a/antarest/matrixstore/matrix_garbage_collector.py b/antarest/matrixstore/matrix_garbage_collector.py index 340d038f15..eecbf19f96 100644 --- a/antarest/matrixstore/matrix_garbage_collector.py +++ b/antarest/matrixstore/matrix_garbage_collector.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import time from os import listdir diff --git a/antarest/matrixstore/model.py b/antarest/matrixstore/model.py index aa9a4a91a9..244cafadca 100644 --- a/antarest/matrixstore/model.py +++ b/antarest/matrixstore/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import typing as t import uuid diff --git a/antarest/matrixstore/repository.py b/antarest/matrixstore/repository.py index 8f3e78f082..a6d5733d66 100644 --- a/antarest/matrixstore/repository.py +++ b/antarest/matrixstore/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import hashlib import logging import typing as t diff --git a/antarest/matrixstore/service.py b/antarest/matrixstore/service.py index 33623c7fb4..7e9450fdec 100644 --- a/antarest/matrixstore/service.py +++ b/antarest/matrixstore/service.py @@ -1,6 +1,17 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import io -import json import logging import tempfile import typing as t @@ -19,6 +30,7 @@ from antarest.core.filetransfer.service import FileTransferManager from antarest.core.jwt import JWTUser from antarest.core.requests import RequestParameters, UserHasNotPermissionError +from antarest.core.serialization import from_json from antarest.core.tasks.model import TaskResult, TaskType from antarest.core.tasks.service import ITaskService, TaskUpdateNotifier from antarest.core.utils.fastapi_sqlalchemy import db @@ -213,6 +225,7 @@ def create_by_importation(self, file: UploadFile, is_json: bool = False) -> t.Li A list of `MatrixInfoDTO` objects containing the SHA256 hash of the imported matrices. """ with file.file as f: + assert file.filename is not None if file.content_type == "application/zip": with contextlib.closing(f): buffer = io.BytesIO(f.read()) @@ -250,7 +263,7 @@ def _file_importation(self, file: bytes, *, is_json: bool = False) -> str: A SHA256 hash that identifies the imported matrix. """ if is_json: - obj = json.loads(file) + obj = from_json(file) content = MatrixContent(**obj) return self.create(content.data) # noinspection PyTypeChecker diff --git a/antarest/matrixstore/uri_resolver_service.py b/antarest/matrixstore/uri_resolver_service.py index 01717c57bd..d35870029d 100644 --- a/antarest/matrixstore/uri_resolver_service.py +++ b/antarest/matrixstore/uri_resolver_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re from typing import Optional, Tuple diff --git a/antarest/matrixstore/web.py b/antarest/matrixstore/web.py index 523176b241..e50fddfbab 100644 --- a/antarest/matrixstore/web.py +++ b/antarest/matrixstore/web.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from pathlib import Path from typing import Any, List, Optional diff --git a/antarest/utils.py b/antarest/service_creator.py similarity index 76% rename from antarest/utils.py rename to antarest/service_creator.py index 1f61717ada..5859806a61 100644 --- a/antarest/utils.py +++ b/antarest/service_creator.py @@ -1,21 +1,29 @@ -import datetime +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging +import typing as t from enum import Enum from pathlib import Path -from typing import Any, Dict, Mapping, Optional, Tuple import redis -import sqlalchemy.ext.baked # type: ignore -import uvicorn # type: ignore -from fastapi import FastAPI -from fastapi_jwt_auth import AuthJWT # type: ignore from ratelimit import RateLimitMiddleware # type: ignore from ratelimit.backends.redis import RedisBackend # type: ignore from ratelimit.backends.simple import MemoryBackend # type: ignore -from sqlalchemy import create_engine +from sqlalchemy import create_engine # type: ignore from sqlalchemy.engine.base import Engine # type: ignore from sqlalchemy.pool import NullPool # type: ignore +from antarest.core.application import AppBuildContext from antarest.core.cache.main import build_cache from antarest.core.config import Config from antarest.core.filetransfer.main import build_filetransfer_service @@ -46,7 +54,7 @@ logger = logging.getLogger(__name__) -SESSION_ARGS: Mapping[str, bool] = { +SESSION_ARGS: t.Mapping[str, bool] = { "autocommit": False, "expire_on_commit": False, "autoflush": False, @@ -75,7 +83,7 @@ def init_db_engine( ) -> Engine: if auto_upgrade_db: upgrade_db(config_file) - connect_args: Dict[str, Any] = {} + connect_args: t.Dict[str, t.Any] = {} if config.db.db_url.startswith("sqlite"): connect_args["check_same_thread"] = False else: @@ -101,24 +109,24 @@ def init_db_engine( return engine -def create_event_bus(application: Optional[FastAPI], config: Config) -> Tuple[IEventBus, Optional[redis.Redis]]: # type: ignore +def create_event_bus(app_ctxt: t.Optional[AppBuildContext], config: Config) -> t.Tuple[IEventBus, t.Optional[redis.Redis]]: # type: ignore redis_client = new_redis_instance(config.redis) if config.redis is not None else None return ( - build_eventbus(application, config, True, redis_client), + build_eventbus(app_ctxt, config, True, redis_client), redis_client, ) def create_core_services( - application: Optional[FastAPI], config: Config -) -> Tuple[ICache, IEventBus, ITaskService, FileTransferManager, LoginService, MatrixService, StudyService,]: - event_bus, redis_client = create_event_bus(application, config) + app_ctxt: t.Optional[AppBuildContext], config: Config +) -> t.Tuple[ICache, IEventBus, ITaskService, FileTransferManager, LoginService, MatrixService, StudyService,]: + event_bus, redis_client = create_event_bus(app_ctxt, config) cache = build_cache(config=config, redis_client=redis_client) - filetransfer_service = build_filetransfer_service(application, event_bus, config) - task_service = build_taskjob_manager(application, config, event_bus) - login_service = build_login(application, config, event_bus=event_bus) + filetransfer_service = build_filetransfer_service(app_ctxt, event_bus, config) + task_service = build_taskjob_manager(app_ctxt, config, event_bus) + login_service = build_login(app_ctxt, config, event_bus=event_bus) matrix_service = build_matrix_service( - application, + app_ctxt, config=config, file_transfer_manager=filetransfer_service, task_service=task_service, @@ -126,7 +134,7 @@ def create_core_services( service=None, ) study_service = build_study_service( - application, + app_ctxt, config, matrix_service=matrix_service, cache=cache, @@ -148,8 +156,8 @@ def create_core_services( def create_watcher( config: Config, - application: Optional[FastAPI], - study_service: Optional[StudyService] = None, + app_ctxt: t.Optional[AppBuildContext], + study_service: t.Optional[StudyService] = None, ) -> Watcher: if study_service: watcher = Watcher( @@ -158,24 +166,24 @@ def create_watcher( task_service=study_service.task_service, ) else: - _, _, task_service, _, _, _, study_service = create_core_services(application, config) + _, _, task_service, _, _, _, study_service = create_core_services(app_ctxt, config) watcher = Watcher( config=config, study_service=study_service, task_service=task_service, ) - if application: - application.include_router(create_watcher_routes(watcher=watcher, config=config)) + if app_ctxt: + app_ctxt.api_root.include_router(create_watcher_routes(watcher=watcher, config=config)) return watcher def create_matrix_gc( config: Config, - application: Optional[FastAPI], - study_service: Optional[StudyService] = None, - matrix_service: Optional[MatrixService] = None, + app_ctxt: t.Optional[AppBuildContext], + study_service: t.Optional[StudyService] = None, + matrix_service: t.Optional[MatrixService] = None, ) -> MatrixGarbageCollector: if study_service and matrix_service: return MatrixGarbageCollector( @@ -184,7 +192,7 @@ def create_matrix_gc( matrix_service=matrix_service, ) else: - _, _, _, _, _, matrix_service, study_service = create_core_services(application, config) + _, _, _, _, _, matrix_service, study_service = create_core_services(app_ctxt, config) return MatrixGarbageCollector( config=config, study_service=study_service, @@ -196,7 +204,7 @@ def create_archive_worker( config: Config, workspace: str, local_root: Path = Path("/"), - event_bus: Optional[IEventBus] = None, + event_bus: t.Optional[IEventBus] = None, ) -> AbstractWorker: if not event_bus: event_bus, _ = create_event_bus(None, config) @@ -206,15 +214,17 @@ def create_archive_worker( def create_simulator_worker( config: Config, matrix_service: MatrixService, - event_bus: Optional[IEventBus] = None, + event_bus: t.Optional[IEventBus] = None, ) -> AbstractWorker: if not event_bus: event_bus, _ = create_event_bus(None, config) return SimulatorWorker(event_bus, matrix_service, config) -def create_services(config: Config, application: Optional[FastAPI], create_all: bool = False) -> Dict[str, Any]: - services: Dict[str, Any] = {} +def create_services( + config: Config, app_ctxt: t.Optional[AppBuildContext], create_all: bool = False +) -> t.Dict[str, t.Any]: + services: t.Dict[str, t.Any] = {} ( cache, @@ -224,12 +234,12 @@ def create_services(config: Config, application: Optional[FastAPI], create_all: user_service, matrix_service, study_service, - ) = create_core_services(application, config) + ) = create_core_services(app_ctxt, config) - maintenance_service = build_maintenance_manager(application, config=config, cache=cache, event_bus=event_bus) + maintenance_service = build_maintenance_manager(app_ctxt, config=config, cache=cache, event_bus=event_bus) launcher = build_launcher( - application, + app_ctxt, config, study_service=study_service, event_bus=event_bus, @@ -238,13 +248,13 @@ def create_services(config: Config, application: Optional[FastAPI], create_all: cache=cache, ) - watcher = create_watcher(config=config, application=application, study_service=study_service) + watcher = create_watcher(config=config, app_ctxt=app_ctxt, study_service=study_service) services["watcher"] = watcher if config.server.services and Module.MATRIX_GC.value in config.server.services or create_all: matrix_garbage_collector = create_matrix_gc( config=config, - application=application, + app_ctxt=app_ctxt, study_service=study_service, matrix_service=matrix_service, ) diff --git a/antarest/singleton_services.py b/antarest/singleton_services.py index 3f3f94a116..3b2373cc0c 100644 --- a/antarest/singleton_services.py +++ b/antarest/singleton_services.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import time from pathlib import Path from typing import Dict, List, cast @@ -7,8 +19,7 @@ from antarest.core.logging.utils import configure_logger from antarest.core.utils.fastapi_sqlalchemy import DBSessionMiddleware from antarest.core.utils.utils import get_local_path -from antarest.study.storage.auto_archive_service import AutoArchiveService -from antarest.utils import ( +from antarest.service_creator import ( SESSION_ARGS, Module, create_archive_worker, @@ -18,6 +29,7 @@ create_watcher, init_db_engine, ) +from antarest.study.storage.auto_archive_service import AutoArchiveService def _init(config_file: Path, services_list: List[Module]) -> Dict[Module, IService]: @@ -44,13 +56,13 @@ def _init(config_file: Path, services_list: List[Module]) -> Dict[Module, IServi services: Dict[Module, IService] = {} if Module.WATCHER in services_list: - watcher = create_watcher(config=config, application=None, study_service=study_service) + watcher = create_watcher(config=config, app_ctxt=None, study_service=study_service) services[Module.WATCHER] = watcher if Module.MATRIX_GC in services_list: matrix_gc = create_matrix_gc( config=config, - application=None, + app_ctxt=None, study_service=study_service, matrix_service=matrix_service, ) diff --git a/antarest/study/__init__.py b/antarest/study/__init__.py index 8b13789179..058c6b221a 100644 --- a/antarest/study/__init__.py +++ b/antarest/study/__init__.py @@ -1 +1,11 @@ - +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/business/__init__.py b/antarest/study/business/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/business/__init__.py +++ b/antarest/study/business/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/business/adequacy_patch_management.py b/antarest/study/business/adequacy_patch_management.py index 7d837df7b6..ddc2214891 100644 --- a/antarest/study/business/adequacy_patch_management.py +++ b/antarest/study/business/adequacy_patch_management.py @@ -1,7 +1,20 @@ -from typing import Any, Dict, List, Optional +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from typing import Any, Dict, List from pydantic.types import StrictBool, confloat, conint +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import GENERAL_DATA_PATH, FieldInfo, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study @@ -17,18 +30,19 @@ class PriceTakingOrder(EnumIgnoreCase): ThresholdType = confloat(ge=0) +@all_optional_model class AdequacyPatchFormFields(FormFieldsBaseModel): # version 830 - enable_adequacy_patch: Optional[StrictBool] - ntc_from_physical_areas_out_to_physical_areas_in_adequacy_patch: Optional[StrictBool] - ntc_between_physical_areas_out_adequacy_patch: Optional[StrictBool] + enable_adequacy_patch: StrictBool + ntc_from_physical_areas_out_to_physical_areas_in_adequacy_patch: StrictBool + ntc_between_physical_areas_out_adequacy_patch: StrictBool # version 850 - price_taking_order: Optional[PriceTakingOrder] - include_hurdle_cost_csr: Optional[StrictBool] - check_csr_cost_function: Optional[StrictBool] - threshold_initiate_curtailment_sharing_rule: Optional[ThresholdType] # type: ignore - threshold_display_local_matching_rule_violations: Optional[ThresholdType] # type: ignore - threshold_csr_variable_bounds_relaxation: Optional[conint(ge=0, strict=True)] # type: ignore + price_taking_order: PriceTakingOrder + include_hurdle_cost_csr: StrictBool + check_csr_cost_function: StrictBool + threshold_initiate_curtailment_sharing_rule: ThresholdType # type: ignore + threshold_display_local_matching_rule_violations: ThresholdType # type: ignore + threshold_csr_variable_bounds_relaxation: conint(ge=0, strict=True) # type: ignore ADEQUACY_PATCH_PATH = f"{GENERAL_DATA_PATH}/adequacy patch" diff --git a/antarest/study/business/advanced_parameters_management.py b/antarest/study/business/advanced_parameters_management.py index 46c58f36d6..3e68ff0aa1 100644 --- a/antarest/study/business/advanced_parameters_management.py +++ b/antarest/study/business/advanced_parameters_management.py @@ -1,9 +1,22 @@ -from typing import Any, Dict, List, Optional - -from pydantic import validator +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from typing import Any, Dict, List + +from pydantic import field_validator from pydantic.types import StrictInt, StrictStr from antarest.core.exceptions import InvalidFieldForVersionError +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import GENERAL_DATA_PATH, FieldInfo, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study @@ -60,33 +73,34 @@ class RenewableGenerationModeling(EnumIgnoreCase): CLUSTERS = "clusters" +@all_optional_model class AdvancedParamsFormFields(FormFieldsBaseModel): # Advanced parameters - accuracy_on_correlation: Optional[StrictStr] + accuracy_on_correlation: StrictStr # Other preferences - initial_reservoir_levels: Optional[InitialReservoirLevel] - power_fluctuations: Optional[PowerFluctuation] - shedding_policy: Optional[SheddingPolicy] - hydro_pricing_mode: Optional[HydroPricingMode] - hydro_heuristic_policy: Optional[HydroHeuristicPolicy] - unit_commitment_mode: Optional[UnitCommitmentMode] - number_of_cores_mode: Optional[SimulationCore] - day_ahead_reserve_management: Optional[ReserveManagement] - renewable_generation_modelling: Optional[RenewableGenerationModeling] + initial_reservoir_levels: InitialReservoirLevel + power_fluctuations: PowerFluctuation + shedding_policy: SheddingPolicy + hydro_pricing_mode: HydroPricingMode + hydro_heuristic_policy: HydroHeuristicPolicy + unit_commitment_mode: UnitCommitmentMode + number_of_cores_mode: SimulationCore + day_ahead_reserve_management: ReserveManagement + renewable_generation_modelling: RenewableGenerationModeling # Seeds - seed_tsgen_wind: Optional[StrictInt] - seed_tsgen_load: Optional[StrictInt] - seed_tsgen_hydro: Optional[StrictInt] - seed_tsgen_thermal: Optional[StrictInt] - seed_tsgen_solar: Optional[StrictInt] - seed_tsnumbers: Optional[StrictInt] - seed_unsupplied_energy_costs: Optional[StrictInt] - seed_spilled_energy_costs: Optional[StrictInt] - seed_thermal_costs: Optional[StrictInt] - seed_hydro_costs: Optional[StrictInt] - seed_initial_reservoir_levels: Optional[StrictInt] - - @validator("accuracy_on_correlation") + seed_tsgen_wind: StrictInt + seed_tsgen_load: StrictInt + seed_tsgen_hydro: StrictInt + seed_tsgen_thermal: StrictInt + seed_tsgen_solar: StrictInt + seed_tsnumbers: StrictInt + seed_unsupplied_energy_costs: StrictInt + seed_spilled_energy_costs: StrictInt + seed_thermal_costs: StrictInt + seed_hydro_costs: StrictInt + seed_initial_reservoir_levels: StrictInt + + @field_validator("accuracy_on_correlation") def check_accuracy_on_correlation(cls, v: str) -> str: sanitized_v = v.strip().replace(" ", "") if not sanitized_v: diff --git a/antarest/study/business/aggregator_management.py b/antarest/study/business/aggregator_management.py index ac88b9d82b..a040faf1de 100644 --- a/antarest/study/business/aggregator_management.py +++ b/antarest/study/business/aggregator_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import typing as t from enum import Enum diff --git a/antarest/study/business/all_optional_meta.py b/antarest/study/business/all_optional_meta.py index 06ddc012d8..7a8440226b 100644 --- a/antarest/study/business/all_optional_meta.py +++ b/antarest/study/business/all_optional_meta.py @@ -1,84 +1,46 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +import copy import typing as t -import pydantic.fields -import pydantic.main -from pydantic import BaseModel +from pydantic import BaseModel, create_model from antarest.core.utils.string import to_camel_case +ModelClass = t.TypeVar("ModelClass", bound=BaseModel) -class AllOptionalMetaclass(pydantic.main.ModelMetaclass): - """ - Metaclass that makes all fields of a Pydantic model optional. - - Usage: - class MyModel(BaseModel, metaclass=AllOptionalMetaclass): - field1: str - field2: int - ... - Instances of the model can be created even if not all fields are provided during initialization. - Default values, when provided, are used unless `use_none` is set to `True`. +def all_optional_model(model: t.Type[ModelClass]) -> t.Type[ModelClass]: """ + This decorator can be used to make all fields of a pydantic model optionals. - def __new__( - cls: t.Type["AllOptionalMetaclass"], - name: str, - bases: t.Tuple[t.Type[t.Any], ...], - namespaces: t.Dict[str, t.Any], - use_none: bool = False, - **kwargs: t.Dict[str, t.Any], - ) -> t.Any: - """ - Create a new instance of the metaclass. - - Args: - name: Name of the class to create. - bases: Base classes of the class to create (a Pydantic model). - namespaces: namespace of the class to create that defines the fields of the model. - use_none: If `True`, the default value of the fields is set to `None`. - Note that this field is not part of the Pydantic model, but it is an extension. - **kwargs: Additional keyword arguments used by the metaclass. - """ - # Modify the annotations of the class (but not of the ancestor classes) - # in order to make all fields optional. - # If the current model inherits from another model, the annotations of the ancestor models - # are not modified, because the fields are already converted to `ModelField`. - annotations = namespaces.get("__annotations__", {}) - for field_name, field_type in annotations.items(): - if not field_name.startswith("__"): - # Making already optional fields optional is not a problem (nothing is changed). - annotations[field_name] = t.Optional[field_type] - namespaces["__annotations__"] = annotations - - if use_none: - # Modify the namespace fields to set their default value to `None`. - for field_name, field_info in namespaces.items(): - if isinstance(field_info, pydantic.fields.FieldInfo): - field_info.default = None - field_info.default_factory = None - - # Create the class: all annotations are converted into `ModelField`. - instance = super().__new__(cls, name, bases, namespaces, **kwargs) - - # Modify the inherited fields of the class to make them optional - # and set their default value to `None`. - model_field: pydantic.fields.ModelField - for field_name, model_field in instance.__fields__.items(): - model_field.required = False - model_field.allow_none = True - if use_none: - model_field.default = None - model_field.default_factory = None - model_field.field_info.default = None - - return instance + Args: + model: The pydantic model to modify. + Returns: + The modified model. + """ + kwargs = {} + for field_name, field_info in model.model_fields.items(): + new = copy.deepcopy(field_info) + new.default = None + new.annotation = t.Optional[field_info.annotation] # type: ignore + kwargs[field_name] = (new.annotation, new) -MODEL = t.TypeVar("MODEL", bound=t.Type[BaseModel]) + return create_model(f"Partial{model.__name__}", __base__=model, __module__=model.__module__, **kwargs) # type: ignore -def camel_case_model(model: MODEL) -> MODEL: +def camel_case_model(model: t.Type[BaseModel]) -> t.Type[BaseModel]: """ This decorator can be used to modify a model to use camel case aliases. @@ -88,7 +50,14 @@ def camel_case_model(model: MODEL) -> MODEL: Returns: The modified model. """ - model.__config__.alias_generator = to_camel_case - for field_name, field in model.__fields__.items(): - field.alias = to_camel_case(field_name) + model.model_config["alias_generator"] = to_camel_case + + # Manually overriding already defined alias names (in base classes), + # otherwise they have precedence over generated ones. + # TODO There is probably a better way to handle those cases + for field_name, field in model.model_fields.items(): + new_alias = to_camel_case(field_name) + field.alias = new_alias + field.validation_alias = new_alias + field.serialization_alias = new_alias return model diff --git a/antarest/study/business/allocation_management.py b/antarest/study/business/allocation_management.py index 8c539ceac3..79c22f26cd 100644 --- a/antarest/study/business/allocation_management.py +++ b/antarest/study/business/allocation_management.py @@ -1,8 +1,22 @@ -from typing import Dict, List +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from typing import Dict, List, Union import numpy import numpy as np -from pydantic import conlist, root_validator, validator +from annotated_types import Len +from pydantic import ValidationInfo, field_validator, model_validator +from typing_extensions import Annotated from antarest.core.exceptions import AllocationDataNotFound, AreaNotFound from antarest.study.business.area_management import AreaInfoDTO @@ -24,9 +38,9 @@ class AllocationFormFields(FormFieldsBaseModel): allocation: List[AllocationField] - @root_validator - def check_allocation(cls, values: Dict[str, List[AllocationField]]) -> Dict[str, List[AllocationField]]: - allocation = values.get("allocation", []) + @model_validator(mode="after") + def check_allocation(self) -> "AllocationFormFields": + allocation = self.allocation if not allocation: raise ValueError("allocation must not be empty") @@ -44,7 +58,7 @@ def check_allocation(cls, values: Dict[str, List[AllocationField]]) -> Dict[str, if sum(a.coefficient for a in allocation) <= 0: raise ValueError("sum of allocation coefficients must be positive") - return values + return self class AllocationMatrix(FormFieldsBaseModel): @@ -55,14 +69,14 @@ class AllocationMatrix(FormFieldsBaseModel): data: 2D-array matrix of consumption coefficients """ - index: conlist(str, min_items=1) # type: ignore - columns: conlist(str, min_items=1) # type: ignore + index: Annotated[List[str], Len(min_length=1)] + columns: Annotated[List[str], Len(min_length=1)] data: List[List[float]] # NonNegativeFloat not necessary # noinspection PyMethodParameters - @validator("data") + @field_validator("data", mode="before") def validate_hydro_allocation_matrix( - cls, data: List[List[float]], values: Dict[str, List[str]] + cls, data: List[List[float]], values: Union[Dict[str, List[str]], ValidationInfo] ) -> List[List[float]]: """ Validate the hydraulic allocation matrix. @@ -77,8 +91,9 @@ def validate_hydro_allocation_matrix( """ array = np.array(data) - rows = len(values.get("index", [])) - cols = len(values.get("columns", [])) + new_values = values if isinstance(values, dict) else values.data + rows = len(new_values.get("index", [])) + cols = len(new_values.get("columns", [])) if array.size == 0: raise ValueError("allocation matrix must not be empty") @@ -124,7 +139,7 @@ def get_allocation_data(self, study: Study, area_id: str) -> Dict[str, List[Allo if not allocation_data: raise AllocationDataNotFound(area_id) - return allocation_data.get("[allocation]", {}) + return allocation_data.get("[allocation]", {}) # type: ignore def get_allocation_form_fields( self, all_areas: List[AreaInfoDTO], study: Study, area_id: str @@ -148,13 +163,10 @@ def get_allocation_form_fields( allocations = self.get_allocation_data(study, area_id) filtered_allocations = {area: value for area, value in allocations.items() if area in areas_ids} - - return AllocationFormFields.construct( - allocation=[ - AllocationField.construct(area_id=area, coefficient=value) - for area, value in filtered_allocations.items() - ] - ) + final_allocations = [ + AllocationField.construct(area_id=area, coefficient=value) for area, value in filtered_allocations.items() + ] + return AllocationFormFields.model_validate({"allocation": final_allocations}) def set_allocation_form_fields( self, diff --git a/antarest/study/business/area_management.py b/antarest/study/business/area_management.py index 6c87d8cb80..5682a6fa60 100644 --- a/antarest/study/business/area_management.py +++ b/antarest/study/business/area_management.py @@ -1,13 +1,25 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import enum import logging import re import typing as t -from pydantic import BaseModel, Extra, Field +from pydantic import BaseModel, Field from antarest.core.exceptions import ConfigFileNotFound, DuplicateAreaName, LayerNotAllowedToBeDeleted, LayerNotFound from antarest.core.model import JSON -from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model +from antarest.study.business.all_optional_meta import all_optional_model, camel_case_model 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 @@ -38,8 +50,8 @@ class AreaType(enum.Enum): class AreaCreationDTO(BaseModel): name: str type: AreaType - metadata: t.Optional[PatchArea] - set: t.Optional[t.List[str]] + metadata: t.Optional[PatchArea] = None + set: t.Optional[t.List[str]] = None # review: is this class necessary? @@ -48,7 +60,7 @@ class ClusterInfoDTO(PatchCluster): name: str enabled: bool = True unitcount: int = 0 - nominalcapacity: int = 0 + nominalcapacity: float = 0 group: t.Optional[str] = None min_stable_power: t.Optional[int] = None min_up_time: t.Optional[int] = None @@ -70,7 +82,7 @@ class LayerInfoDTO(BaseModel): areas: t.List[str] -class UpdateAreaUi(BaseModel, extra="forbid", allow_population_by_field_name=True): +class UpdateAreaUi(BaseModel, extra="forbid", populate_by_name=True): """ DTO for updating area UI @@ -95,7 +107,7 @@ class UpdateAreaUi(BaseModel, extra="forbid", allow_population_by_field_name=Tru ... } >>> model = UpdateAreaUi(**obj) - >>> pprint(model.dict(by_alias=True), width=80) + >>> pprint(model.model_dump(by_alias=True), width=80) {'colorRgb': [230, 108, 44], 'layerColor': {0: '230, 108, 44', 4: '230, 108, 44', @@ -167,9 +179,9 @@ class _BaseAreaDTO( OptimizationProperties.FilteringSection, OptimizationProperties.ModalOptimizationSection, AdequacyPathProperties.AdequacyPathSection, - extra=Extra.forbid, + extra="forbid", validate_assignment=True, - allow_population_by_field_name=True, + populate_by_name=True, ): """ Represents an area output. @@ -188,8 +200,9 @@ class _BaseAreaDTO( # noinspection SpellCheckingInspection +@all_optional_model @camel_case_model -class AreaOutput(_BaseAreaDTO, metaclass=AllOptionalMetaclass, use_none=True): +class AreaOutput(_BaseAreaDTO): """ DTO object use to get the area information using a flat structure. """ @@ -215,30 +228,32 @@ def from_model( obj = { "average_unsupplied_energy_cost": average_unsupplied_energy_cost, "average_spilled_energy_cost": average_spilled_energy_cost, - **area_folder.optimization.filtering.dict(by_alias=False), - **area_folder.optimization.nodal_optimization.dict(by_alias=False), + **area_folder.optimization.filtering.model_dump(by_alias=False), + **area_folder.optimization.nodal_optimization.model_dump(by_alias=False), # adequacy_patch is only available if study version >= 830. - **(area_folder.adequacy_patch.adequacy_patch.dict(by_alias=False) if area_folder.adequacy_patch else {}), + **( + area_folder.adequacy_patch.adequacy_patch.model_dump(by_alias=False) + if area_folder.adequacy_patch + else {} + ), } return cls(**obj) def _to_optimization(self) -> OptimizationProperties: - obj = {name: getattr(self, name) for name in OptimizationProperties.FilteringSection.__fields__} + obj = {name: getattr(self, name) for name in OptimizationProperties.FilteringSection.model_fields} filtering_section = OptimizationProperties.FilteringSection(**obj) - obj = {name: getattr(self, name) for name in OptimizationProperties.ModalOptimizationSection.__fields__} + obj = {name: getattr(self, name) for name in OptimizationProperties.ModalOptimizationSection.model_fields} nodal_optimization_section = OptimizationProperties.ModalOptimizationSection(**obj) - return OptimizationProperties( - filtering=filtering_section, - nodal_optimization=nodal_optimization_section, - ) + args = {"filtering": filtering_section, "nodal_optimization": nodal_optimization_section} + return OptimizationProperties.model_validate(args) def _to_adequacy_patch(self) -> t.Optional[AdequacyPathProperties]: - obj = {name: getattr(self, name) for name in AdequacyPathProperties.AdequacyPathSection.__fields__} + obj = {name: getattr(self, name) for name in AdequacyPathProperties.AdequacyPathSection.model_fields} # If all fields are `None`, the object is empty. if all(value is None for value in obj.values()): return None adequacy_path_section = AdequacyPathProperties.AdequacyPathSection(**obj) - return AdequacyPathProperties(adequacy_patch=adequacy_path_section) + return AdequacyPathProperties.model_validate({"adequacy_patch": adequacy_path_section}) @property def area_folder(self) -> AreaFolder: @@ -347,7 +362,7 @@ def update_areas_props( for area_id, update_area in update_areas_by_ids.items(): # Update the area properties. old_area = old_areas_by_ids[area_id] - new_area = old_area.copy(update=update_area.dict(by_alias=False, exclude_none=True)) + new_area = old_area.copy(update=update_area.model_dump(by_alias=False, exclude_none=True)) new_areas_by_ids[area_id] = new_area # Convert the DTO to a configuration object and update the configuration file. @@ -728,7 +743,7 @@ def update_thermal_cluster_metadata( id=area_id, name=file_study.config.areas[area_id].name, type=AreaType.AREA, - metadata=patch.areas.get(area_id, PatchArea()).dict(), + metadata=patch.areas.get(area_id, PatchArea()), thermals=self._get_clusters(file_study, area_id, patch), set=None, ) diff --git a/antarest/study/business/areas/__init__.py b/antarest/study/business/areas/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/business/areas/__init__.py +++ b/antarest/study/business/areas/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/business/areas/hydro_management.py b/antarest/study/business/areas/hydro_management.py index e0a52ee4e1..d464336d93 100644 --- a/antarest/study/business/areas/hydro_management.py +++ b/antarest/study/business/areas/hydro_management.py @@ -1,7 +1,20 @@ -from typing import Any, Dict, List, Optional - -from pydantic import Field - +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from typing import Any, Dict, List, Optional, Union + +from pydantic import Field, model_validator + +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.utils import FieldInfo, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study from antarest.study.storage.storage_service import StudyStorageService @@ -24,22 +37,23 @@ class InflowStructure(FormFieldsBaseModel): ) +@all_optional_model class ManagementOptionsFormFields(FormFieldsBaseModel): - inter_daily_breakdown: Optional[float] = Field(ge=0) - intra_daily_modulation: Optional[float] = Field(ge=1) - inter_monthly_breakdown: Optional[float] = Field(ge=0) - reservoir: Optional[bool] - reservoir_capacity: Optional[float] = Field(ge=0) - follow_load: Optional[bool] - use_water: Optional[bool] - hard_bounds: Optional[bool] - initialize_reservoir_date: Optional[int] = Field(ge=0, le=11) - use_heuristic: Optional[bool] - power_to_level: Optional[bool] - use_leeway: Optional[bool] - leeway_low: Optional[float] = Field(ge=0) - leeway_up: Optional[float] = Field(ge=0) - pumping_efficiency: Optional[float] = Field(ge=0) + inter_daily_breakdown: float = Field(ge=0) + intra_daily_modulation: float = Field(ge=1) + inter_monthly_breakdown: float = Field(ge=0) + reservoir: bool + reservoir_capacity: float = Field(ge=0) + follow_load: bool + use_water: bool + hard_bounds: bool + initialize_reservoir_date: int = Field(ge=0, le=11) + use_heuristic: bool + power_to_level: bool + use_leeway: bool + leeway_low: float = Field(ge=0) + leeway_up: float = Field(ge=0) + pumping_efficiency: float = Field(ge=0) HYDRO_PATH = "input/hydro/hydro" diff --git a/antarest/study/business/areas/properties_management.py b/antarest/study/business/areas/properties_management.py index 0bccdad784..ac3dbb902a 100644 --- a/antarest/study/business/areas/properties_management.py +++ b/antarest/study/business/areas/properties_management.py @@ -1,10 +1,23 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import typing as t from builtins import sorted -from pydantic import root_validator +from pydantic import model_validator from antarest.core.exceptions import ChildNotFoundError +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.utils import FieldInfo, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study from antarest.study.storage.rawstudy.model.filesystem.config.area import AdequacyPatchMode @@ -37,18 +50,19 @@ def decode_filter(encoded_value: t.Set[str], current_filter: t.Optional[str] = N return ", ".join(sort_filter_options(encoded_value)) +@all_optional_model class PropertiesFormFields(FormFieldsBaseModel): - energy_cost_unsupplied: t.Optional[float] - energy_cost_spilled: t.Optional[float] - non_dispatch_power: t.Optional[bool] - dispatch_hydro_power: t.Optional[bool] - other_dispatch_power: t.Optional[bool] - filter_synthesis: t.Optional[t.Set[str]] - filter_by_year: t.Optional[t.Set[str]] + energy_cost_unsupplied: float + energy_cost_spilled: float + non_dispatch_power: bool + dispatch_hydro_power: bool + other_dispatch_power: bool + filter_synthesis: t.Set[str] + filter_by_year: t.Set[str] # version 830 - adequacy_patch_mode: t.Optional[AdequacyPatchMode] + adequacy_patch_mode: AdequacyPatchMode - @root_validator + @model_validator(mode="before") def validation(cls, values: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: filters = { "filter_synthesis": values.get("filter_synthesis"), @@ -131,7 +145,7 @@ def get_value(field_info: FieldInfo) -> t.Any: encode = field_info.get("encode") or (lambda x: x) return encode(val) - return PropertiesFormFields.construct(**{name: get_value(info) for name, info in FIELDS_INFO.items()}) + return PropertiesFormFields.model_construct(**{name: get_value(info) for name, info in FIELDS_INFO.items()}) def set_field_values( self, diff --git a/antarest/study/business/areas/renewable_management.py b/antarest/study/business/areas/renewable_management.py index 1009c9d22c..12af8abdb5 100644 --- a/antarest/study/business/areas/renewable_management.py +++ b/antarest/study/business/areas/renewable_management.py @@ -1,12 +1,23 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import collections -import json import typing as t -from pydantic import validator +from pydantic import field_validator from antarest.core.exceptions import DuplicateRenewableCluster, RenewableClusterConfigNotFound, RenewableClusterNotFound from antarest.core.model import JSON -from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model +from antarest.study.business.all_optional_meta import all_optional_model, camel_case_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Study @@ -34,23 +45,26 @@ class TimeSeriesInterpretation(EnumIgnoreCase): PRODUCTION_FACTOR = "production-factor" +@all_optional_model @camel_case_model -class RenewableClusterInput(RenewableProperties, metaclass=AllOptionalMetaclass, use_none=True): +class RenewableClusterInput(RenewableProperties): """ Model representing the data structure required to edit an existing renewable cluster. """ class Config: + populate_by_name = True + @staticmethod - def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: + def json_schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: schema["example"] = RenewableClusterInput( group="Gas", name="Gas Cluster XY", enabled=False, - unitCount=100, - nominalCapacity=1000.0, - tsInterpretation="power-generation", - ) + unit_count=100, + nominal_capacity=1000.0, + ts_interpretation="power-generation", + ).model_dump() class RenewableClusterCreation(RenewableClusterInput): @@ -59,7 +73,7 @@ class RenewableClusterCreation(RenewableClusterInput): """ # noinspection Pydantic - @validator("name", pre=True) + @field_validator("name", mode="before") def validate_name(cls, name: t.Optional[str]) -> str: """ Validator to check if the name is not empty. @@ -69,28 +83,29 @@ def validate_name(cls, name: t.Optional[str]) -> str: return name def to_config(self, study_version: t.Union[str, int]) -> RenewableConfigType: - values = self.dict(by_alias=False, exclude_none=True) + values = self.model_dump(by_alias=False, exclude_none=True) return create_renewable_config(study_version=study_version, **values) +@all_optional_model @camel_case_model -class RenewableClusterOutput(RenewableConfig, metaclass=AllOptionalMetaclass, use_none=True): +class RenewableClusterOutput(RenewableConfig): """ Model representing the output data structure to display the details of a renewable cluster. """ class Config: @staticmethod - def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: + def json_schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: schema["example"] = RenewableClusterOutput( id="Gas cluster YZ", group="Gas", name="Gas Cluster YZ", enabled=False, - unitCount=100, - nominalCapacity=1000.0, - tsInterpretation="power-generation", - ) + unit_count=100, + nominal_capacity=1000.0, + ts_interpretation="power-generation", + ).model_dump() def create_renewable_output( @@ -99,7 +114,7 @@ def create_renewable_output( config: t.Mapping[str, t.Any], ) -> "RenewableClusterOutput": obj = create_renewable_config(study_version=study_version, **config, id=cluster_id) - kwargs = obj.dict(by_alias=False) + kwargs = obj.model_dump(by_alias=False) return RenewableClusterOutput(**kwargs) @@ -206,7 +221,7 @@ def _make_create_cluster_cmd(self, area_id: str, cluster: RenewableConfigType) - command = CreateRenewablesCluster( area_id=area_id, cluster_name=cluster.id, - parameters=cluster.dict(by_alias=True, exclude={"id"}), + parameters=cluster.model_dump(mode="json", by_alias=True, exclude={"id"}), command_context=self.storage_service.variant_study_service.command_factory.command_context, ) return command @@ -269,16 +284,16 @@ def update_cluster( old_config = create_renewable_config(study_version, **values) # use Python values to synchronize Config and Form values - new_values = cluster_data.dict(by_alias=False, exclude_none=True) + new_values = cluster_data.model_dump(by_alias=False, exclude_none=True) new_config = old_config.copy(exclude={"id"}, update=new_values) - new_data = json.loads(new_config.json(by_alias=True, exclude={"id"})) + new_data = new_config.model_dump(mode="json", by_alias=True, exclude={"id"}) # create the dict containing the new values using aliases - data: t.Dict[str, t.Any] = { - field.alias: new_data[field.alias] - for field_name, field in new_config.__fields__.items() - if field_name in new_values - } + data: t.Dict[str, t.Any] = {} + for field_name, field in new_config.model_fields.items(): + if field_name in new_values: + name = field.alias if field.alias else field_name + data[name] = new_data[name] # create the update config commands with the modified data command_context = self.storage_service.variant_study_service.command_factory.command_context @@ -288,7 +303,7 @@ def update_cluster( ] execute_or_add_commands(study, file_study, commands, self.storage_service) - values = new_config.dict(by_alias=False) + values = new_config.model_dump(by_alias=False) return RenewableClusterOutput(**values, id=cluster_id) def delete_clusters(self, study: Study, area_id: str, cluster_ids: t.Sequence[str]) -> None: @@ -340,7 +355,7 @@ def duplicate_cluster( # Cluster duplication current_cluster = self.get_cluster(study, area_id, source_id) current_cluster.name = new_cluster_name - creation_form = RenewableClusterCreation(**current_cluster.dict(by_alias=False, exclude={"id"})) + creation_form = RenewableClusterCreation(**current_cluster.model_dump(by_alias=False, exclude={"id"})) new_config = creation_form.to_config(study.version) create_cluster_cmd = self._make_create_cluster_cmd(area_id, new_config) @@ -358,7 +373,7 @@ def duplicate_cluster( execute_or_add_commands(study, self._get_file_study(study), commands, self.storage_service) - return RenewableClusterOutput(**new_config.dict(by_alias=False)) + return RenewableClusterOutput(**new_config.model_dump(by_alias=False)) def update_renewables_props( self, @@ -375,17 +390,17 @@ def update_renewables_props( for renewable_id, update_cluster in update_renewables_by_ids.items(): # Update the renewable cluster properties. old_cluster = old_renewables_by_ids[renewable_id] - new_cluster = old_cluster.copy(update=update_cluster.dict(by_alias=False, exclude_none=True)) + new_cluster = old_cluster.copy(update=update_cluster.model_dump(by_alias=False, exclude_none=True)) new_renewables_by_areas[area_id][renewable_id] = new_cluster # Convert the DTO to a configuration object and update the configuration file. properties = create_renewable_config( - study.version, **new_cluster.dict(by_alias=False, exclude_none=True) + study.version, **new_cluster.model_dump(by_alias=False, exclude_none=True) ) path = _CLUSTER_PATH.format(area_id=area_id, cluster_id=renewable_id) cmd = UpdateConfig( target=path, - data=json.loads(properties.json(by_alias=True, exclude={"id"})), + data=properties.model_dump(mode="json", by_alias=True, exclude={"id"}), command_context=self.storage_service.variant_study_service.command_factory.command_context, ) commands.append(cmd) diff --git a/antarest/study/business/areas/st_storage_management.py b/antarest/study/business/areas/st_storage_management.py index 776f57a039..dcb5db5dc8 100644 --- a/antarest/study/business/areas/st_storage_management.py +++ b/antarest/study/business/areas/st_storage_management.py @@ -1,12 +1,21 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import collections -import functools -import json import operator import typing as t import numpy as np -from pydantic import BaseModel, Extra, root_validator, validator -from requests.structures import CaseInsensitiveDict +from pydantic import BaseModel, field_validator, model_validator from typing_extensions import Literal from antarest.core.exceptions import ( @@ -18,7 +27,8 @@ STStorageNotFound, ) from antarest.core.model import JSON -from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model +from antarest.core.requests import CaseInsensitiveDict +from antarest.study.business.all_optional_meta import all_optional_model, camel_case_model from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Study from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id @@ -37,15 +47,16 @@ from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig +@all_optional_model @camel_case_model -class STStorageInput(STStorage880Properties, metaclass=AllOptionalMetaclass, use_none=True): +class STStorageInput(STStorage880Properties): """ Model representing the form used to EDIT an existing short-term storage. """ class Config: @staticmethod - def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: + def json_schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: schema["example"] = STStorageInput( name="Siemens Battery", group=STStorageGroup.BATTERY, @@ -55,7 +66,7 @@ def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: efficiency=0.94, initial_level=0.5, initial_level_optim=True, - ) + ).model_dump() class STStorageCreation(STStorageInput): @@ -64,7 +75,7 @@ class STStorageCreation(STStorageInput): """ # noinspection Pydantic - @validator("name", pre=True) + @field_validator("name", mode="before") def validate_name(cls, name: t.Optional[str]) -> str: """ Validator to check if the name is not empty. @@ -75,19 +86,20 @@ def validate_name(cls, name: t.Optional[str]) -> str: # noinspection PyUnusedLocal def to_config(self, study_version: t.Union[str, int]) -> STStorageConfigType: - values = self.dict(by_alias=False, exclude_none=True) + values = self.model_dump(by_alias=False, exclude_none=True) return create_st_storage_config(study_version=study_version, **values) +@all_optional_model @camel_case_model -class STStorageOutput(STStorage880Config, metaclass=AllOptionalMetaclass, use_none=True): +class STStorageOutput(STStorage880Config): """ Model representing the form used to display the details of a short-term storage entry. """ class Config: @staticmethod - def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: + def json_schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: schema["example"] = STStorageOutput( id="siemens_battery", name="Siemens Battery", @@ -97,7 +109,7 @@ def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: reservoir_capacity=600, efficiency=0.94, initial_level_optim=True, - ) + ).model_dump() # ============= @@ -119,13 +131,13 @@ class STStorageMatrix(BaseModel): """ class Config: - extra = Extra.forbid + extra = "forbid" data: t.List[t.List[float]] index: t.List[int] columns: t.List[int] - @validator("data") + @field_validator("data") def validate_time_series(cls, data: t.List[t.List[float]]) -> t.List[t.List[float]]: """ Validator to check the integrity of the time series data. @@ -160,7 +172,7 @@ class STStorageMatrices(BaseModel): """ class Config: - extra = Extra.forbid + extra = "forbid" pmax_injection: STStorageMatrix pmax_withdrawal: STStorageMatrix @@ -168,7 +180,7 @@ class Config: upper_rule_curve: STStorageMatrix inflows: STStorageMatrix - @validator( + @field_validator( "pmax_injection", "pmax_withdrawal", "lower_rule_curve", @@ -183,23 +195,18 @@ def validate_time_series(cls, matrix: STStorageMatrix) -> STStorageMatrix: raise ValueError("Matrix values should be between 0 and 1") return matrix - @root_validator() - def validate_rule_curve( - cls, values: t.MutableMapping[str, STStorageMatrix] - ) -> t.MutableMapping[str, STStorageMatrix]: + @model_validator(mode="after") + def validate_rule_curve(self) -> "STStorageMatrices": """ Validator to ensure 'lower_rule_curve' values are less than or equal to 'upper_rule_curve' values. """ - if "lower_rule_curve" in values and "upper_rule_curve" in values: - lower_rule_curve = values["lower_rule_curve"] - upper_rule_curve = values["upper_rule_curve"] - lower_array = np.array(lower_rule_curve.data, dtype=np.float64) - upper_array = np.array(upper_rule_curve.data, dtype=np.float64) - # noinspection PyUnresolvedReferences - if (lower_array > upper_array).any(): - raise ValueError("Each 'lower_rule_curve' value must be lower or equal to each 'upper_rule_curve'") - return values + lower_array = np.array(self.lower_rule_curve.data, dtype=np.float64) + upper_array = np.array(self.upper_rule_curve.data, dtype=np.float64) + if (lower_array > upper_array).any(): + raise ValueError("Each 'lower_rule_curve' value must be lower or equal to each 'upper_rule_curve'") + + return self # noinspection SpellCheckingInspection @@ -237,7 +244,7 @@ def create_storage_output( config: t.Mapping[str, t.Any], ) -> "STStorageOutput": obj = create_st_storage_config(study_version=study_version, **config, id=cluster_id) - kwargs = obj.dict(by_alias=False) + kwargs = obj.model_dump(by_alias=False) return STStorageOutput(**kwargs) @@ -381,17 +388,17 @@ def update_storages_props( for storage_id, update_cluster in update_storages_by_ids.items(): # Update the storage cluster properties. old_cluster = old_storages_by_ids[storage_id] - new_cluster = old_cluster.copy(update=update_cluster.dict(by_alias=False, exclude_none=True)) + new_cluster = old_cluster.copy(update=update_cluster.model_dump(by_alias=False, exclude_none=True)) new_storages_by_areas[area_id][storage_id] = new_cluster # Convert the DTO to a configuration object and update the configuration file. properties = create_st_storage_config( - study.version, **new_cluster.dict(by_alias=False, exclude_none=True) + study.version, **new_cluster.model_dump(by_alias=False, exclude_none=True) ) path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) cmd = UpdateConfig( target=path, - data=json.loads(properties.json(by_alias=True, exclude={"id"})), + data=properties.model_dump(mode="json", by_alias=True, exclude={"id"}), command_context=self.storage_service.variant_study_service.command_factory.command_context, ) commands.append(cmd) @@ -460,16 +467,16 @@ def update_storage( old_config = create_st_storage_config(study_version, **values) # use Python values to synchronize Config and Form values - new_values = form.dict(by_alias=False, exclude_none=True) + new_values = form.model_dump(by_alias=False, exclude_none=True) new_config = old_config.copy(exclude={"id"}, update=new_values) - new_data = json.loads(new_config.json(by_alias=True, exclude={"id"})) + new_data = new_config.model_dump(mode="json", by_alias=True, exclude={"id"}) # create the dict containing the new values using aliases - data: t.Dict[str, t.Any] = { - field.alias: new_data[field.alias] - for field_name, field in new_config.__fields__.items() - if field_name in new_values - } + data: t.Dict[str, t.Any] = {} + for field_name, field in new_config.model_fields.items(): + if field_name in new_values: + name = field.alias if field.alias else field_name + data[name] = new_data[name] # create the update config commands with the modified data command_context = self.storage_service.variant_study_service.command_factory.command_context @@ -480,7 +487,7 @@ def update_storage( ] execute_or_add_commands(study, file_study, commands, self.storage_service) - values = new_config.dict(by_alias=False) + values = new_config.model_dump(by_alias=False) return STStorageOutput(**values, id=storage_id) def delete_storages( @@ -542,7 +549,7 @@ def duplicate_cluster(self, study: Study, area_id: str, source_id: str, new_clus # We should remove the field 'enabled' for studies before v8.8 as it didn't exist if int(study.version) < 880: fields_to_exclude.add("enabled") - creation_form = STStorageCreation(**current_cluster.dict(by_alias=False, exclude=fields_to_exclude)) + creation_form = STStorageCreation(**current_cluster.model_dump(by_alias=False, exclude=fields_to_exclude)) new_config = creation_form.to_config(study.version) create_cluster_cmd = self._make_create_cluster_cmd(area_id, new_config) @@ -571,7 +578,7 @@ def duplicate_cluster(self, study: Study, area_id: str, source_id: str, new_clus execute_or_add_commands(study, self._get_file_study(study), commands, self.storage_service) - return STStorageOutput(**new_config.dict(by_alias=False)) + return STStorageOutput(**new_config.model_dump(by_alias=False)) def get_matrix( self, @@ -672,17 +679,18 @@ def validate_matrices( Returns: bool: True if validation is successful. """ - # Create a partial function to retrieve matrix objects - get_matrix_obj = functools.partial(self._get_matrix_obj, study, area_id, storage_id) + + def validate_matrix(matrix_type: STStorageTimeSeries) -> STStorageMatrix: + return STStorageMatrix.model_validate(self._get_matrix_obj(study, area_id, storage_id, matrix_type)) # Validate matrices by constructing the `STStorageMatrices` object # noinspection SpellCheckingInspection STStorageMatrices( - pmax_injection=get_matrix_obj("pmax_injection"), - pmax_withdrawal=get_matrix_obj("pmax_withdrawal"), - lower_rule_curve=get_matrix_obj("lower_rule_curve"), - upper_rule_curve=get_matrix_obj("upper_rule_curve"), - inflows=get_matrix_obj("inflows"), + pmax_injection=validate_matrix("pmax_injection"), + pmax_withdrawal=validate_matrix("pmax_withdrawal"), + lower_rule_curve=validate_matrix("lower_rule_curve"), + upper_rule_curve=validate_matrix("upper_rule_curve"), + inflows=validate_matrix("inflows"), ) # Validation successful diff --git a/antarest/study/business/areas/thermal_management.py b/antarest/study/business/areas/thermal_management.py index 205965eb54..c1a06068aa 100644 --- a/antarest/study/business/areas/thermal_management.py +++ b/antarest/study/business/areas/thermal_management.py @@ -1,9 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import collections -import json import typing as t from pathlib import Path -from pydantic import validator +from pydantic import field_validator from antarest.core.exceptions import ( DuplicateThermalCluster, @@ -13,7 +24,7 @@ WrongMatrixHeightError, ) from antarest.core.model import JSON -from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model +from antarest.study.business.all_optional_meta import all_optional_model, camel_case_model from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Study from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id @@ -42,33 +53,35 @@ _ALL_CLUSTERS_PATH = "input/thermal/clusters" +@all_optional_model @camel_case_model -class ThermalClusterInput(Thermal870Properties, metaclass=AllOptionalMetaclass, use_none=True): +class ThermalClusterInput(Thermal870Properties): """ Model representing the data structure required to edit an existing thermal cluster within a study. """ class Config: @staticmethod - def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: + def json_schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: schema["example"] = ThermalClusterInput( group="Gas", name="Gas Cluster XY", enabled=False, - unitCount=100, - nominalCapacity=1000.0, - genTs="use global", + unit_count=100, + nominal_capacity=1000.0, + gen_ts="use global", co2=7.0, - ) + ).model_dump() +@camel_case_model class ThermalClusterCreation(ThermalClusterInput): """ Model representing the data structure required to create a new thermal cluster within a study. """ # noinspection Pydantic - @validator("name", pre=True) + @field_validator("name", mode="before") def validate_name(cls, name: t.Optional[str]) -> str: """ Validator to check if the name is not empty. @@ -78,29 +91,30 @@ def validate_name(cls, name: t.Optional[str]) -> str: return name def to_config(self, study_version: t.Union[str, int]) -> ThermalConfigType: - values = self.dict(by_alias=False, exclude_none=True) + values = self.model_dump(by_alias=False, exclude_none=True) return create_thermal_config(study_version=study_version, **values) +@all_optional_model @camel_case_model -class ThermalClusterOutput(Thermal870Config, metaclass=AllOptionalMetaclass, use_none=True): +class ThermalClusterOutput(Thermal870Config): """ Model representing the output data structure to display the details of a thermal cluster within a study. """ class Config: @staticmethod - def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: + def json_schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: schema["example"] = ThermalClusterOutput( id="Gas cluster YZ", group="Gas", name="Gas Cluster YZ", enabled=False, - unitCount=100, - nominalCapacity=1000.0, - genTs="use global", + unit_count=100, + nominal_capacity=1000.0, + gen_ts="use global", co2=7.0, - ) + ).model_dump() def create_thermal_output( @@ -109,7 +123,7 @@ def create_thermal_output( config: t.Mapping[str, t.Any], ) -> "ThermalClusterOutput": obj = create_thermal_config(study_version=study_version, **config, id=cluster_id) - kwargs = obj.dict(by_alias=False) + kwargs = obj.model_dump(by_alias=False) return ThermalClusterOutput(**kwargs) @@ -240,15 +254,17 @@ def update_thermals_props( for thermal_id, update_cluster in update_thermals_by_ids.items(): # Update the thermal cluster properties. old_cluster = old_thermals_by_ids[thermal_id] - new_cluster = old_cluster.copy(update=update_cluster.dict(by_alias=False, exclude_none=True)) + new_cluster = old_cluster.copy(update=update_cluster.model_dump(by_alias=False, exclude_none=True)) new_thermals_by_areas[area_id][thermal_id] = new_cluster # Convert the DTO to a configuration object and update the configuration file. - properties = create_thermal_config(study.version, **new_cluster.dict(by_alias=False, exclude_none=True)) + properties = create_thermal_config( + study.version, **new_cluster.model_dump(by_alias=False, exclude_none=True) + ) path = _CLUSTER_PATH.format(area_id=area_id, cluster_id=thermal_id) cmd = UpdateConfig( target=path, - data=json.loads(properties.json(by_alias=True, exclude={"id"})), + data=properties.model_dump(mode="json", by_alias=True, exclude={"id"}), command_context=self.storage_service.variant_study_service.command_factory.command_context, ) commands.append(cmd) @@ -290,12 +306,13 @@ def create_cluster(self, study: Study, area_id: str, cluster_data: ThermalCluste def _make_create_cluster_cmd(self, area_id: str, cluster: ThermalConfigType) -> CreateCluster: # NOTE: currently, in the `CreateCluster` class, there is a confusion # between the cluster name and the cluster ID (which is a section name). - command = CreateCluster( - area_id=area_id, - cluster_name=cluster.id, - parameters=cluster.dict(by_alias=True, exclude={"id"}), - command_context=self.storage_service.variant_study_service.command_factory.command_context, - ) + args = { + "area_id": area_id, + "cluster_name": cluster.id, + "parameters": cluster.model_dump(mode="json", by_alias=True, exclude={"id"}), + "command_context": self.storage_service.variant_study_service.command_factory.command_context, + } + command = CreateCluster.model_validate(args) return command def update_cluster( @@ -334,16 +351,16 @@ def update_cluster( old_config = create_thermal_config(study_version, **values) # Use Python values to synchronize Config and Form values - new_values = cluster_data.dict(by_alias=False, exclude_none=True) + new_values = cluster_data.model_dump(by_alias=False, exclude_none=True) new_config = old_config.copy(exclude={"id"}, update=new_values) - new_data = json.loads(new_config.json(by_alias=True, exclude={"id"})) + new_data = new_config.model_dump(mode="json", by_alias=True, exclude={"id"}) # create the dict containing the new values using aliases - data: t.Dict[str, t.Any] = { - field.alias: new_data[field.alias] - for field_name, field in new_config.__fields__.items() - if field_name in new_values - } + data: t.Dict[str, t.Any] = {} + for field_name, field in new_config.model_fields.items(): + if field_name in new_values: + name = field.alias if field.alias else field_name + data[name] = new_data[name] # create the update config commands with the modified data command_context = self.storage_service.variant_study_service.command_factory.command_context @@ -353,8 +370,8 @@ def update_cluster( ] execute_or_add_commands(study, file_study, commands, self.storage_service) - values = new_config.dict(by_alias=False) - return ThermalClusterOutput(**values, id=cluster_id) + values = {**new_config.model_dump(mode="json", by_alias=False), "id": cluster_id} + return ThermalClusterOutput.model_validate(values) def delete_clusters(self, study: Study, area_id: str, cluster_ids: t.Sequence[str]) -> None: """ @@ -406,7 +423,7 @@ def duplicate_cluster( # Cluster duplication source_cluster = self.get_cluster(study, area_id, source_id) source_cluster.name = new_cluster_name - creation_form = ThermalClusterCreation(**source_cluster.dict(by_alias=False, exclude={"id"})) + creation_form = ThermalClusterCreation(**source_cluster.model_dump(by_alias=False, exclude={"id"})) new_config = creation_form.to_config(study.version) create_cluster_cmd = self._make_create_cluster_cmd(area_id, new_config) @@ -439,7 +456,7 @@ def duplicate_cluster( execute_or_add_commands(study, self._get_file_study(study), commands, self.storage_service) - return ThermalClusterOutput(**new_config.dict(by_alias=False)) + return ThermalClusterOutput(**new_config.model_dump(by_alias=False)) def validate_series(self, study: Study, area_id: str, cluster_id: str) -> bool: lower_cluster_id = cluster_id.lower() diff --git a/antarest/study/business/binding_constraint_management.py b/antarest/study/business/binding_constraint_management.py index bf23d5ccbc..3c55ef38da 100644 --- a/antarest/study/business/binding_constraint_management.py +++ b/antarest/study/business/binding_constraint_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import collections import copy import json @@ -5,8 +17,7 @@ import typing as t import numpy as np -from pydantic import BaseModel, Field, root_validator, validator -from requests.utils import CaseInsensitiveDict +from pydantic import BaseModel, Field, field_validator, model_validator from antarest.core.exceptions import ( BindingConstraintNotFound, @@ -20,6 +31,7 @@ WrongMatrixHeightError, ) from antarest.core.model import JSON +from antarest.core.requests import CaseInsensitiveDict from antarest.core.utils.string import to_camel_case from antarest.study.business.all_optional_meta import camel_case_model from antarest.study.business.utils import execute_or_add_commands @@ -126,12 +138,12 @@ class ConstraintTerm(BaseModel): data: the constraint term data (link or cluster), if any. """ - id: t.Optional[str] - weight: t.Optional[float] - offset: t.Optional[int] - data: t.Optional[t.Union[LinkTerm, ClusterTerm]] + id: t.Optional[str] = None + weight: t.Optional[float] = None + offset: t.Optional[int] = None + data: t.Optional[t.Union[LinkTerm, ClusterTerm]] = None - @validator("id") + @field_validator("id") def id_to_lower(cls, v: t.Optional[str]) -> t.Optional[str]: """Ensure the ID is lower case.""" if v is None: @@ -262,7 +274,7 @@ class ConstraintInput(BindingConstraintMatrices, ConstraintInput870): class ConstraintCreation(ConstraintInput): name: str - @root_validator(pre=True) + @model_validator(mode="before") def check_matrices_dimensions(cls, values: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: for _key in ["time_step"] + [m.value for m in TermMatrices]: _camel = to_camel_case(_key) @@ -313,20 +325,19 @@ def check_matrices_dimensions(cls, values: t.Dict[str, t.Any]) -> t.Dict[str, t. raise ValueError(err_msg) -@camel_case_model class ConstraintOutputBase(BindingConstraintPropertiesBase): id: str name: str terms: t.MutableSequence[ConstraintTerm] = Field(default_factory=lambda: []) + # I have to redefine the time_step attribute to give him another alias. + time_step: t.Optional[BindingConstraintFrequency] = Field(DEFAULT_TIMESTEP, alias="timeStep") # type: ignore -@camel_case_model class ConstraintOutput830(ConstraintOutputBase): - filter_year_by_year: str = "" - filter_synthesis: str = "" + filter_year_by_year: str = Field(default="", alias="filterYearByYear") + filter_synthesis: str = Field(default="", alias="filterSynthesis") -@camel_case_model class ConstraintOutput870(ConstraintOutput830): group: str = DEFAULT_GROUP @@ -370,7 +381,7 @@ def _get_references_by_widths( continue matrix_height = matrix.shape[0] - expected_height = EXPECTED_MATRIX_SHAPES[bc.time_step][0] + expected_height = EXPECTED_MATRIX_SHAPES[bc.time_step][0] # type: ignore if matrix_height != expected_height: raise WrongMatrixHeightError( f"The binding constraint '{bc.name}' should have {expected_height} rows, currently: {matrix_height}" @@ -441,17 +452,22 @@ def parse_and_add_terms(key: str, value: t.Any, adapted_constraint: ConstraintOu id=key, weight=weight, offset=offset, - data={ - "area1": term_data[0], - "area2": term_data[1], - }, + data=LinkTerm.model_validate( + { + "area1": term_data[0], + "area2": term_data[1], + } + ), ) ) # Cluster term else: adapted_constraint.terms.append( ConstraintTerm( - id=key, weight=weight, offset=offset, data={"area": term_data[0], "cluster": term_data[1]} + id=key, + weight=weight, + offset=offset, + data=ClusterTerm.model_validate({"area": term_data[0], "cluster": term_data[1]}), ) ) @@ -599,7 +615,7 @@ def get_grouped_constraints(self, study: Study) -> t.Mapping[str, t.Sequence[Con storage_service = self.storage_service.get_storage(study) file_study = storage_service.get_raw(study) config = file_study.tree.get(["input", "bindingconstraints", "bindingconstraints"]) - grouped_constraints = CaseInsensitiveDict() # type: ignore + grouped_constraints = CaseInsensitiveDict() for constraint in config.values(): constraint_config = self.constraint_model_adapter(constraint, int(study.version)) @@ -708,7 +724,10 @@ def create_binding_constraint( check_attributes_coherence(data, version, data.operator or DEFAULT_OPERATOR) - new_constraint = {"name": data.name, **json.loads(data.json(exclude={"terms", "name"}, exclude_none=True))} + new_constraint = { + "name": data.name, + **data.model_dump(mode="json", exclude={"terms", "name"}, exclude_none=True), + } args = { **new_constraint, "command_context": self.storage_service.variant_study_service.command_factory.command_context, @@ -747,7 +766,7 @@ def update_binding_constraint( upd_constraint = { "id": binding_constraint_id, - **json.loads(data.json(exclude={"terms", "name"}, exclude_none=True)), + **data.model_dump(mode="json", exclude={"terms", "name"}, exclude_none=True), } args = { **upd_constraint, @@ -768,7 +787,7 @@ def update_binding_constraint( if updated_matrices: time_step = data.time_step or existing_constraint.time_step command.validates_and_fills_matrices( - time_step=time_step, specific_matrices=updated_matrices, version=study_version, create=False + time_step=time_step, specific_matrices=updated_matrices, version=study_version, create=False # type: ignore ) execute_or_add_commands(study, file_study, [command], self.storage_service) @@ -922,11 +941,9 @@ def _update_constraint_with_terms( coeffs = { term_id: [term.weight, term.offset] if term.offset else [term.weight] for term_id, term in terms.items() } - command = UpdateBindingConstraint( - id=bc.id, - coeffs=coeffs, - command_context=self.storage_service.variant_study_service.command_factory.command_context, - ) + command_context = self.storage_service.variant_study_service.command_factory.command_context + args = {"id": bc.id, "coeffs": coeffs, "command_context": command_context} + command = UpdateBindingConstraint.model_validate(args) file_study = self.storage_service.get_storage(study).get_raw(study) execute_or_add_commands(study, file_study, [command], self.storage_service) @@ -949,7 +966,7 @@ def update_constraint_terms( if update_mode == "add": for term in constraint_terms: if term.data is None: - raise InvalidConstraintTerm(binding_constraint_id, term.json()) + raise InvalidConstraintTerm(binding_constraint_id, term.model_dump_json()) constraint = self.get_binding_constraint(study, binding_constraint_id) existing_terms = collections.OrderedDict((term.generate_id(), term) for term in constraint.terms) diff --git a/antarest/study/business/config_management.py b/antarest/study/business/config_management.py index 35f46c01ca..856a48b535 100644 --- a/antarest/study/business/config_management.py +++ b/antarest/study/business/config_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Dict, List, Optional from antarest.study.business.utils import execute_or_add_commands diff --git a/antarest/study/business/correlation_management.py b/antarest/study/business/correlation_management.py index b9abcff2f2..c05b293b3e 100644 --- a/antarest/study/business/correlation_management.py +++ b/antarest/study/business/correlation_management.py @@ -1,13 +1,25 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Management of spatial correlations between the different generators. The generators are of the same category and can be hydraulic, wind, load or solar. """ import collections -from typing import Dict, List, Sequence +from typing import Dict, List, Sequence, Union import numpy as np import numpy.typing as npt -from pydantic import conlist, validator +from pydantic import ValidationInfo, field_validator from antarest.core.exceptions import AreaNotFound from antarest.study.business.area_management import AreaInfoDTO @@ -28,7 +40,7 @@ class AreaCoefficientItem(FormFieldsBaseModel): """ class Config: - allow_population_by_field_name = True + populate_by_name = True area_id: str coefficient: float @@ -45,7 +57,7 @@ class CorrelationFormFields(FormFieldsBaseModel): correlation: List[AreaCoefficientItem] # noinspection PyMethodParameters - @validator("correlation") + @field_validator("correlation") def check_correlation(cls, correlation: List[AreaCoefficientItem]) -> List[AreaCoefficientItem]: if not correlation: raise ValueError("correlation must not be empty") @@ -72,13 +84,21 @@ class CorrelationMatrix(FormFieldsBaseModel): data: A 2D-array matrix of correlation coefficients. """ - index: conlist(str, min_items=1) # type: ignore - columns: conlist(str, min_items=1) # type: ignore + index: List[str] + columns: List[str] data: List[List[float]] # NonNegativeFloat not necessary + @field_validator("index", "columns", mode="before") + def validate_list_length(cls, values: List[str]) -> List[str]: + if len(values) == 0: + raise ValueError("correlation matrix cannot have 0 columns/index") + return values + # noinspection PyMethodParameters - @validator("data") - def validate_correlation_matrix(cls, data: List[List[float]], values: Dict[str, List[str]]) -> List[List[float]]: + @field_validator("data", mode="before") + def validate_correlation_matrix( + cls, data: List[List[float]], values: Union[Dict[str, List[str]], ValidationInfo] + ) -> List[List[float]]: """ Validates the correlation matrix by checking its shape and range of coefficients. @@ -100,8 +120,9 @@ def validate_correlation_matrix(cls, data: List[List[float]], values: Dict[str, """ array = np.array(data) - rows = len(values.get("index", [])) - cols = len(values.get("columns", [])) + new_values = values if isinstance(values, dict) else values.data + rows = len(new_values.get("index", [])) + cols = len(new_values.get("columns", [])) if array.size == 0: raise ValueError("correlation matrix must not be empty") @@ -117,7 +138,7 @@ def validate_correlation_matrix(cls, data: List[List[float]], values: Dict[str, return data class Config: - schema_extra = { + json_schema_extra = { "example": { "columns": ["north", "east", "south", "west"], "data": [ diff --git a/antarest/study/business/district_manager.py b/antarest/study/business/district_manager.py index 5a214c284c..c642d61531 100644 --- a/antarest/study/business/district_manager.py +++ b/antarest/study/business/district_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List from pydantic import BaseModel @@ -57,16 +69,19 @@ def get_districts(self, study: Study) -> List[DistrictInfoDTO]: """ file_study = self.storage_service.get_storage(study).get_raw(study) all_areas = list(file_study.config.areas) - return [ - DistrictInfoDTO( - id=district_id, - name=district.name, - areas=district.get_areas(all_areas), - output=district.output, - comments=file_study.tree.get(["input", "areas", "sets", district_id]).get("comments", ""), + districts = [] + for district_id, district in file_study.config.sets.items(): + assert district.name is not None + districts.append( + DistrictInfoDTO( + id=district_id, + name=district.name, + areas=district.get_areas(all_areas), + output=district.output, + comments=file_study.tree.get(["input", "areas", "sets", district_id]).get("comments", ""), + ) ) - for district_id, district in file_study.config.sets.items() - ] + return districts def create_district( self, @@ -136,14 +151,14 @@ def update_district( file_study = self.storage_service.get_storage(study).get_raw(study) if district_id not in file_study.config.sets: raise DistrictNotFound(district_id) - areas = frozenset(dto.areas or []) - all_areas = frozenset(file_study.config.areas) + areas = set(dto.areas or []) + all_areas = set(file_study.config.areas) if invalid_areas := areas - all_areas: raise AreaNotFound(*invalid_areas) command = UpdateDistrict( id=district_id, base_filter=DistrictBaseFilter.remove_all, - filter_items=areas, + filter_items=dto.areas or [], output=dto.output, comments=dto.comments, command_context=self.storage_service.variant_study_service.command_factory.command_context, diff --git a/antarest/study/business/enum_ignore_case.py b/antarest/study/business/enum_ignore_case.py index aa784aa9c4..2259d229f7 100644 --- a/antarest/study/business/enum_ignore_case.py +++ b/antarest/study/business/enum_ignore_case.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import enum import typing diff --git a/antarest/study/business/general_management.py b/antarest/study/business/general_management.py index 4cf2dc62e0..088f8708fe 100644 --- a/antarest/study/business/general_management.py +++ b/antarest/study/business/general_management.py @@ -1,7 +1,20 @@ -from typing import Any, Dict, List, Optional, cast - -from pydantic import PositiveInt, StrictBool, conint, root_validator - +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from typing import Any, Dict, List, Union, cast + +from pydantic import PositiveInt, StrictBool, ValidationInfo, conint, model_validator + +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import GENERAL_DATA_PATH, FieldInfo, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study @@ -51,39 +64,67 @@ class BuildingMode(EnumIgnoreCase): DayNumberType = conint(ge=1, le=366) +@all_optional_model class GeneralFormFields(FormFieldsBaseModel): - mode: Optional[Mode] - first_day: Optional[DayNumberType] # type: ignore - last_day: Optional[DayNumberType] # type: ignore - horizon: Optional[str] # Don't use `StrictStr` because it can be an int - first_month: Optional[Month] - first_week_day: Optional[WeekDay] - first_january: Optional[WeekDay] - leap_year: Optional[StrictBool] - nb_years: Optional[PositiveInt] - building_mode: Optional[BuildingMode] - selection_mode: Optional[StrictBool] - year_by_year: Optional[StrictBool] - simulation_synthesis: Optional[StrictBool] - mc_scenario: Optional[StrictBool] + mode: Mode + first_day: DayNumberType # type: ignore + last_day: DayNumberType # type: ignore + horizon: Union[str, int] + first_month: Month + first_week_day: WeekDay + first_january: WeekDay + leap_year: StrictBool + nb_years: PositiveInt + building_mode: BuildingMode + selection_mode: StrictBool + year_by_year: StrictBool + simulation_synthesis: StrictBool + mc_scenario: StrictBool # Geographic trimming + Thematic trimming. # For study versions < 710 - filtering: Optional[StrictBool] + filtering: StrictBool # For study versions >= 710 - geographic_trimming: Optional[StrictBool] - thematic_trimming: Optional[StrictBool] - - @root_validator - def day_fields_validation(cls, values: Dict[str, Any]) -> Dict[str, Any]: - first_day = values.get("first_day") - last_day = values.get("last_day") - leap_year = values.get("leap_year") + geographic_trimming: StrictBool + thematic_trimming: StrictBool + + model_config = { + "json_schema_extra": { + "examples": [ + { + "mode": "Economy", + "first_day": 1, + "last_day": 365, + "horizon": "2020", + "first_month": "january", + "first_week_day": "Monday", + "first_january": "Monday", + "leap_year": True, + "nb_years": 5, + "building_mode": "Automatic", + "selection_mode": True, + "year_by_year": True, + "simulation_synthesis": True, + "mc_scenario": True, + "filtering": True, + "geographic_trimming": True, + "thematic_trimming": True, + } + ] + } + } + + @model_validator(mode="before") + def day_fields_validation(cls, values: Union[Dict[str, Any], ValidationInfo]) -> Dict[str, Any]: + new_values = values if isinstance(values, dict) else values.data + first_day = new_values.get("first_day") + last_day = new_values.get("last_day") + leap_year = new_values.get("leap_year") day_fields = [first_day, last_day, leap_year] if all(v is None for v in day_fields): # The user wishes to update another field than these three. # no need to validate anything: - return values + return new_values if any(v is None for v in day_fields): raise ValueError("First day, last day and leap year fields must be defined together") @@ -98,7 +139,7 @@ def day_fields_validation(cls, values: Dict[str, Any]) -> Dict[str, Any]: if last_day > num_days_in_year: raise ValueError(f"Last day cannot be greater than {num_days_in_year}") - return values + return new_values GENERAL = "general" diff --git a/antarest/study/business/link_management.py b/antarest/study/business/link_management.py index 744401772a..6f696d2a5e 100644 --- a/antarest/study/business/link_management.py +++ b/antarest/study/business/link_management.py @@ -1,10 +1,22 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pydantic import BaseModel from antarest.core.exceptions import ConfigFileNotFound from antarest.core.model import JSON -from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model +from antarest.study.business.all_optional_meta import all_optional_model, camel_case_model from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import RawStudy from antarest.study.storage.rawstudy.model.filesystem.config.links import LinkProperties @@ -28,8 +40,9 @@ class LinkInfoDTO(BaseModel): ui: t.Optional[LinkUIDTO] = None +@all_optional_model @camel_case_model -class LinkOutput(LinkProperties, metaclass=AllOptionalMetaclass, use_none=True): +class LinkOutput(LinkProperties): """ DTO object use to get the link information. """ @@ -109,7 +122,7 @@ def get_all_links_props(self, study: RawStudy) -> t.Mapping[t.Tuple[str, str], L for area2_id, properties_cfg in property_map.items(): area1_id, area2_id = sorted([area1_id, area2_id]) properties = LinkProperties(**properties_cfg) - links_by_ids[(area1_id, area2_id)] = LinkOutput(**properties.dict(by_alias=False)) + links_by_ids[(area1_id, area2_id)] = LinkOutput(**properties.model_dump(by_alias=False)) return links_by_ids @@ -125,11 +138,11 @@ def update_links_props( for (area1, area2), update_link_dto in update_links_by_ids.items(): # Update the link properties. old_link_dto = old_links_by_ids[(area1, area2)] - new_link_dto = old_link_dto.copy(update=update_link_dto.dict(by_alias=False, exclude_none=True)) + new_link_dto = old_link_dto.copy(update=update_link_dto.model_dump(by_alias=False, exclude_none=True)) new_links_by_ids[(area1, area2)] = new_link_dto # Convert the DTO to a configuration object and update the configuration file. - properties = LinkProperties(**new_link_dto.dict(by_alias=False)) + properties = LinkProperties(**new_link_dto.model_dump(by_alias=False)) path = f"{_ALL_LINKS_PATH}/{area1}/properties/{area2}" cmd = UpdateConfig( target=path, diff --git a/antarest/study/business/matrix_management.py b/antarest/study/business/matrix_management.py index 282ddebedd..67f809b7e8 100644 --- a/antarest/study/business/matrix_management.py +++ b/antarest/study/business/matrix_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import itertools import logging import operator diff --git a/antarest/study/business/optimization_management.py b/antarest/study/business/optimization_management.py index 5defcc2a2a..cb599d12e2 100644 --- a/antarest/study/business/optimization_management.py +++ b/antarest/study/business/optimization_management.py @@ -1,7 +1,20 @@ -from typing import Any, Dict, List, Optional, Union, cast +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from typing import Any, Dict, List, Union, cast from pydantic.types import StrictBool +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import GENERAL_DATA_PATH, FieldInfo, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study @@ -33,24 +46,20 @@ class SimplexOptimizationRange(EnumIgnoreCase): WEEK = "week" +@all_optional_model class OptimizationFormFields(FormFieldsBaseModel): - binding_constraints: Optional[StrictBool] - hurdle_costs: Optional[StrictBool] - transmission_capacities: Optional[ - Union[ - StrictBool, - Union[LegacyTransmissionCapacities, TransmissionCapacities], - ] - ] - thermal_clusters_min_stable_power: Optional[StrictBool] - thermal_clusters_min_ud_time: Optional[StrictBool] - day_ahead_reserve: Optional[StrictBool] - primary_reserve: Optional[StrictBool] - strategic_reserve: Optional[StrictBool] - spinning_reserve: Optional[StrictBool] - export_mps: Optional[Union[bool, str]] - unfeasible_problem_behavior: Optional[UnfeasibleProblemBehavior] - simplex_optimization_range: Optional[SimplexOptimizationRange] + binding_constraints: StrictBool + hurdle_costs: StrictBool + transmission_capacities: Union[StrictBool, LegacyTransmissionCapacities, TransmissionCapacities] + thermal_clusters_min_stable_power: StrictBool + thermal_clusters_min_ud_time: StrictBool + day_ahead_reserve: StrictBool + primary_reserve: StrictBool + strategic_reserve: StrictBool + spinning_reserve: StrictBool + export_mps: Union[bool, str] + unfeasible_problem_behavior: UnfeasibleProblemBehavior + simplex_optimization_range: SimplexOptimizationRange OPTIMIZATION_PATH = f"{GENERAL_DATA_PATH}/optimization" diff --git a/antarest/study/business/playlist_management.py b/antarest/study/business/playlist_management.py index 89c9f6ea17..fef4a4d2a4 100644 --- a/antarest/study/business/playlist_management.py +++ b/antarest/study/business/playlist_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Dict, List, Union from pydantic.types import StrictBool, StrictFloat, StrictInt diff --git a/antarest/study/business/scenario_builder_management.py b/antarest/study/business/scenario_builder_management.py index 0f7c94f7bb..c8a38b28c3 100644 --- a/antarest/study/business/scenario_builder_management.py +++ b/antarest/study/business/scenario_builder_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import enum import typing as t diff --git a/antarest/study/business/table_mode_management.py b/antarest/study/business/table_mode_management.py index bc31683139..342c1c5abb 100644 --- a/antarest/study/business/table_mode_management.py +++ b/antarest/study/business/table_mode_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import collections import typing as t @@ -83,36 +95,37 @@ def __init__( def _get_table_data_unsafe(self, study: RawStudy, table_type: TableModeType) -> TableDataDTO: if table_type == TableModeType.AREA: areas_map = self._area_manager.get_all_area_props(study) - data = {area_id: area.dict(by_alias=True) for area_id, area in areas_map.items()} + data = {area_id: area.model_dump(by_alias=True) for area_id, area in areas_map.items()} elif table_type == TableModeType.LINK: links_map = self._link_manager.get_all_links_props(study) data = { - f"{area1_id} / {area2_id}": link.dict(by_alias=True) for (area1_id, area2_id), link in links_map.items() + f"{area1_id} / {area2_id}": link.model_dump(by_alias=True) + for (area1_id, area2_id), link in links_map.items() } elif table_type == TableModeType.THERMAL: thermals_by_areas = self._thermal_manager.get_all_thermals_props(study) data = { - f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + f"{area_id} / {cluster_id}": cluster.model_dump(by_alias=True, exclude={"id", "name"}) for area_id, thermals_by_ids in thermals_by_areas.items() for cluster_id, cluster in thermals_by_ids.items() } elif table_type == TableModeType.RENEWABLE: renewables_by_areas = self._renewable_manager.get_all_renewables_props(study) data = { - f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + f"{area_id} / {cluster_id}": cluster.model_dump(by_alias=True, exclude={"id", "name"}) for area_id, renewables_by_ids in renewables_by_areas.items() for cluster_id, cluster in renewables_by_ids.items() } elif table_type == TableModeType.ST_STORAGE: storages_by_areas = self._st_storage_manager.get_all_storages_props(study) data = { - f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + f"{area_id} / {cluster_id}": cluster.model_dump(by_alias=True, exclude={"id", "name"}) for area_id, storages_by_ids in storages_by_areas.items() for cluster_id, cluster in storages_by_ids.items() } elif table_type == TableModeType.BINDING_CONSTRAINT: bc_seq = self._binding_constraint_manager.get_binding_constraints(study) - data = {bc.id: bc.dict(by_alias=True, exclude={"id", "name", "terms"}) for bc in bc_seq} + data = {bc.id: bc.model_dump(by_alias=True, exclude={"id", "name", "terms"}) for bc in bc_seq} else: # pragma: no cover raise NotImplementedError(f"Table type {table_type} not implemented") return data @@ -177,13 +190,13 @@ def update_table_data( # Use AreaOutput to update properties of areas, which may include `None` values area_props_by_ids = {key: AreaOutput(**values) for key, values in data.items()} areas_map = self._area_manager.update_areas_props(study, area_props_by_ids) - data = {area_id: area.dict(by_alias=True, exclude_none=True) for area_id, area in areas_map.items()} + data = {area_id: area.model_dump(by_alias=True, exclude_none=True) for area_id, area in areas_map.items()} return data elif table_type == TableModeType.LINK: links_map = {tuple(key.split(" / ")): LinkOutput(**values) for key, values in data.items()} updated_map = self._link_manager.update_links_props(study, links_map) # type: ignore data = { - f"{area1_id} / {area2_id}": link.dict(by_alias=True) + f"{area1_id} / {area2_id}": link.model_dump(by_alias=True) for (area1_id, area2_id), link in updated_map.items() } return data @@ -195,7 +208,7 @@ def update_table_data( thermals_by_areas[area_id][cluster_id] = ThermalClusterInput(**values) thermals_map = self._thermal_manager.update_thermals_props(study, thermals_by_areas) data = { - f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + f"{area_id} / {cluster_id}": cluster.model_dump(by_alias=True, exclude={"id", "name"}) for area_id, thermals_by_ids in thermals_map.items() for cluster_id, cluster in thermals_by_ids.items() } @@ -208,7 +221,7 @@ def update_table_data( renewables_by_areas[area_id][cluster_id] = RenewableClusterInput(**values) renewables_map = self._renewable_manager.update_renewables_props(study, renewables_by_areas) data = { - f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + f"{area_id} / {cluster_id}": cluster.model_dump(by_alias=True, exclude={"id", "name"}) for area_id, renewables_by_ids in renewables_map.items() for cluster_id, cluster in renewables_by_ids.items() } @@ -221,7 +234,7 @@ def update_table_data( storages_by_areas[area_id][cluster_id] = STStorageInput(**values) storages_map = self._st_storage_manager.update_storages_props(study, storages_by_areas) data = { - f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + f"{area_id} / {cluster_id}": cluster.model_dump(by_alias=True, exclude={"id", "name"}) for area_id, storages_by_ids in storages_map.items() for cluster_id, cluster in storages_by_ids.items() } @@ -229,7 +242,9 @@ def update_table_data( elif table_type == TableModeType.BINDING_CONSTRAINT: bcs_by_ids = {key: ConstraintInput(**values) for key, values in data.items()} bcs_map = self._binding_constraint_manager.update_binding_constraints(study, bcs_by_ids) - return {bc_id: bc.dict(by_alias=True, exclude={"id", "name", "terms"}) for bc_id, bc in bcs_map.items()} + return { + bc_id: bc.model_dump(by_alias=True, exclude={"id", "name", "terms"}) for bc_id, bc in bcs_map.items() + } else: # pragma: no cover raise NotImplementedError(f"Table type {table_type} not implemented") diff --git a/antarest/study/business/thematic_trimming_field_infos.py b/antarest/study/business/thematic_trimming_field_infos.py index 3baabd8014..06086005fd 100644 --- a/antarest/study/business/thematic_trimming_field_infos.py +++ b/antarest/study/business/thematic_trimming_field_infos.py @@ -1,14 +1,27 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ List of fields of the Thematic Trimming panel """ import typing as t -from antarest.study.business.all_optional_meta import AllOptionalMetaclass +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.utils import FormFieldsBaseModel -class ThematicTrimmingFormFields(FormFieldsBaseModel, metaclass=AllOptionalMetaclass, use_none=True): +@all_optional_model +class ThematicTrimmingFormFields(FormFieldsBaseModel): """ This class manages the configuration of result filtering in a simulation. @@ -225,6 +238,5 @@ class ThematicTrimmingFormFields(FormFieldsBaseModel, metaclass=AllOptionalMetac } -def get_fields_info(study_version: t.Union[str, int]) -> t.Mapping[str, t.Mapping[str, t.Any]]: - study_version = int(study_version) +def get_fields_info(study_version: int) -> t.Mapping[str, t.Mapping[str, t.Any]]: return {key: info for key, info in FIELDS_INFO.items() if (info.get("start_version") or 0) <= study_version} diff --git a/antarest/study/business/thematic_trimming_management.py b/antarest/study/business/thematic_trimming_management.py index d4af9f960e..96bd5732d6 100644 --- a/antarest/study/business/thematic_trimming_management.py +++ b/antarest/study/business/thematic_trimming_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.study.business.thematic_trimming_field_infos import ThematicTrimmingFormFields, get_fields_info @@ -37,7 +49,7 @@ def set_field_values(self, study: Study, field_values: ThematicTrimmingFormField Set Thematic Trimming config from the webapp form """ file_study = self.storage_service.get_storage(study).get_raw(study) - field_values_dict = field_values.dict() + field_values_dict = field_values.model_dump() keys_by_bool: t.Dict[bool, t.List[t.Any]] = {True: [], False: []} fields_info = get_fields_info(int(study.version)) diff --git a/antarest/study/business/timeseries_config_management.py b/antarest/study/business/timeseries_config_management.py index 56cf07cfa1..7e77612fd8 100644 --- a/antarest/study/business/timeseries_config_management.py +++ b/antarest/study/business/timeseries_config_management.py @@ -1,8 +1,21 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t -from pydantic import StrictBool, StrictInt, root_validator, validator +from pydantic import StrictBool, StrictInt, field_validator, model_validator from antarest.core.model import JSON +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import GENERAL_DATA_PATH, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study @@ -27,28 +40,30 @@ class SeasonCorrelation(EnumIgnoreCase): ANNUAL = "annual" +@all_optional_model class TSFormFieldsForType(FormFieldsBaseModel): - stochastic_ts_status: t.Optional[StrictBool] - number: t.Optional[StrictInt] - refresh: t.Optional[StrictBool] - refresh_interval: t.Optional[StrictInt] - season_correlation: t.Optional[SeasonCorrelation] - store_in_input: t.Optional[StrictBool] - store_in_output: t.Optional[StrictBool] - intra_modal: t.Optional[StrictBool] - inter_modal: t.Optional[StrictBool] - - + stochastic_ts_status: StrictBool + number: StrictInt + refresh: StrictBool + refresh_interval: StrictInt + season_correlation: SeasonCorrelation + store_in_input: StrictBool + store_in_output: StrictBool + intra_modal: StrictBool + inter_modal: StrictBool + + +@all_optional_model class TSFormFields(FormFieldsBaseModel): - load: t.Optional[TSFormFieldsForType] = None - hydro: t.Optional[TSFormFieldsForType] = None - thermal: t.Optional[TSFormFieldsForType] = None - wind: t.Optional[TSFormFieldsForType] = None - solar: t.Optional[TSFormFieldsForType] = None - renewables: t.Optional[TSFormFieldsForType] = None - ntc: t.Optional[TSFormFieldsForType] = None - - @root_validator(pre=True) + load: TSFormFieldsForType + hydro: TSFormFieldsForType + thermal: TSFormFieldsForType + wind: TSFormFieldsForType + solar: TSFormFieldsForType + renewables: TSFormFieldsForType + ntc: TSFormFieldsForType + + @model_validator(mode="before") def check_type_validity( cls, values: t.Dict[str, t.Optional[TSFormFieldsForType]] ) -> t.Dict[str, t.Optional[TSFormFieldsForType]]: @@ -61,7 +76,7 @@ def has_type(ts_type: TSType) -> bool: ) return values - @validator("thermal") + @field_validator("thermal") def thermal_validation(cls, v: TSFormFieldsForType) -> TSFormFieldsForType: if v.season_correlation is not None: raise ValueError("season_correlation is not allowed for 'thermal' type") @@ -118,7 +133,7 @@ def __set_field_values_for_type( field_values: TSFormFieldsForType, ) -> None: commands: t.List[UpdateConfig] = [] - values = field_values.dict() + values = field_values.model_dump() for field, path in PATH_BY_TS_STR_FIELD.items(): field_val = values[field] diff --git a/antarest/study/business/utils.py b/antarest/study/business/utils.py index 8c4b567b22..1afacecc04 100644 --- a/antarest/study/business/utils.py +++ b/antarest/study/business/utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pydantic import BaseModel @@ -5,7 +17,7 @@ from antarest.core.exceptions import CommandApplicationError from antarest.core.jwt import DEFAULT_ADMIN_USER from antarest.core.requests import RequestParameters -from antarest.core.utils.string import to_camel_case +from antarest.study.business.all_optional_meta import camel_case_model from antarest.study.model import RawStudy, Study from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.storage_service import StudyStorageService @@ -57,12 +69,12 @@ def execute_or_add_commands( ) +@camel_case_model class FormFieldsBaseModel( BaseModel, - alias_generator=to_camel_case, extra="forbid", validate_assignment=True, - allow_population_by_field_name=True, + populate_by_name=True, ): """ Pydantic Model for webapp form diff --git a/antarest/study/business/xpansion_management.py b/antarest/study/business/xpansion_management.py index 66d25860dd..ad459d036f 100644 --- a/antarest/study/business/xpansion_management.py +++ b/antarest/study/business/xpansion_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import http import io @@ -7,17 +19,14 @@ import zipfile from fastapi import HTTPException, UploadFile -from pydantic import BaseModel, Extra, Field, ValidationError, root_validator, validator +from pydantic import BaseModel, Field, ValidationError, field_validator, model_validator from antarest.core.exceptions import BadZipBinary, ChildNotFoundError from antarest.core.model import JSON -from antarest.study.business.all_optional_meta import AllOptionalMetaclass +from antarest.study.business.all_optional_meta import all_optional_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.model import Study -from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy -from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode -from antarest.study.storage.rawstudy.model.filesystem.root.user.expansion.expansion import Expansion from antarest.study.storage.storage_service import StudyStorageService from antarest.study.storage.utils import fix_study_root @@ -62,12 +71,12 @@ class XpansionSensitivitySettings(BaseModel): projection: t.List[str] = Field(default_factory=list, description="List of candidate names to project") capex: bool = Field(default=False, description="Whether to include capex in the sensitivity analysis") - @validator("projection", pre=True) + @field_validator("projection", mode="before") def projection_validation(cls, v: t.Optional[t.Sequence[str]]) -> t.Sequence[str]: return [] if v is None else v -class XpansionSettings(BaseModel, extra=Extra.ignore, validate_assignment=True, allow_population_by_field_name=True): +class XpansionSettings(BaseModel, extra="ignore", validate_assignment=True, populate_by_name=True): """ A data transfer object representing the general settings used for Xpansion. @@ -140,8 +149,8 @@ class XpansionSettings(BaseModel, extra=Extra.ignore, validate_assignment=True, # The sensitivity analysis is optional sensitivity_config: t.Optional[XpansionSensitivitySettings] = None - @root_validator(pre=True) - def normalize_values(cls, values: t.MutableMapping[str, t.Any]) -> t.MutableMapping[str, t.Any]: + @model_validator(mode="before") + def validate_float_values(cls, values: t.MutableMapping[str, t.Any]) -> t.MutableMapping[str, t.Any]: if "relaxed-optimality-gap" in values: values["relaxed_optimality_gap"] = values.pop("relaxed-optimality-gap") @@ -196,7 +205,8 @@ def from_config(cls, config_obj: JSON) -> "GetXpansionSettings": return cls.construct(**config_obj) -class UpdateXpansionSettings(XpansionSettings, metaclass=AllOptionalMetaclass, use_none=True): +@all_optional_model +class UpdateXpansionSettings(XpansionSettings): """ DTO object used to update the Xpansion settings. @@ -207,13 +217,6 @@ class UpdateXpansionSettings(XpansionSettings, metaclass=AllOptionalMetaclass, u # note: for some reason, the alias is not taken into account when using the metaclass, # so we have to redefine the fields with the alias. - - # On the other hand, we make these fields mandatory, because there is an anomaly on the front side: - # When the user does not select any file, the front sends a request without the "yearly-weights" - # or "additional-constraints" field, instead of sending the field with an empty value. - # This is not a problem as long as the front sends a request with all the fields (PUT case), - # but it is a problem for partial requests (PATCH case). - yearly_weights: str = Field( "", alias="yearly-weights", @@ -233,19 +236,21 @@ class XpansionCandidateDTO(BaseModel): name: str link: str annual_cost_per_mw: float = Field(alias="annual-cost-per-mw", ge=0) - unit_size: t.Optional[float] = Field(None, alias="unit-size", ge=0) - max_units: t.Optional[int] = Field(None, alias="max-units", ge=0) - max_investment: t.Optional[float] = Field(None, alias="max-investment", ge=0) - already_installed_capacity: t.Optional[int] = Field(None, alias="already-installed-capacity", ge=0) + unit_size: t.Optional[float] = Field(default=None, alias="unit-size", ge=0) + max_units: t.Optional[int] = Field(default=None, alias="max-units", ge=0) + max_investment: t.Optional[float] = Field(default=None, alias="max-investment", ge=0) + already_installed_capacity: t.Optional[int] = Field(default=None, alias="already-installed-capacity", ge=0) # this is obsolete (replaced by direct/indirect) - link_profile: t.Optional[str] = Field(None, alias="link-profile") + link_profile: t.Optional[str] = Field(default=None, alias="link-profile") # this is obsolete (replaced by direct/indirect) - already_installed_link_profile: t.Optional[str] = Field(None, alias="already-installed-link-profile") - direct_link_profile: t.Optional[str] = Field(None, alias="direct-link-profile") - indirect_link_profile: t.Optional[str] = Field(None, alias="indirect-link-profile") - already_installed_direct_link_profile: t.Optional[str] = Field(None, alias="already-installed-direct-link-profile") + already_installed_link_profile: t.Optional[str] = Field(default=None, alias="already-installed-link-profile") + direct_link_profile: t.Optional[str] = Field(default=None, alias="direct-link-profile") + indirect_link_profile: t.Optional[str] = Field(default=None, alias="indirect-link-profile") + already_installed_direct_link_profile: t.Optional[str] = Field( + default=None, alias="already-installed-direct-link-profile" + ) already_installed_indirect_link_profile: t.Optional[str] = Field( - None, alias="already-installed-indirect-link-profile" + default=None, alias="already-installed-indirect-link-profile" ) @@ -335,9 +340,11 @@ def create_xpansion_configuration(self, study: Study, zipped_config: t.Optional[ raise BadZipBinary("Only zip file are allowed.") xpansion_settings = XpansionSettings() - settings_obj = xpansion_settings.dict(by_alias=True, exclude_none=True, exclude={"sensitivity_config"}) + settings_obj = xpansion_settings.model_dump( + by_alias=True, exclude_none=True, exclude={"sensitivity_config"} + ) if xpansion_settings.sensitivity_config: - sensitivity_obj = xpansion_settings.sensitivity_config.dict(by_alias=True, exclude_none=True) + sensitivity_obj = xpansion_settings.sensitivity_config.model_dump(by_alias=True, exclude_none=True) else: sensitivity_obj = {} @@ -377,7 +384,9 @@ def update_xpansion_settings( logger.info(f"Updating xpansion settings for study '{study.id}'") actual_settings = self.get_xpansion_settings(study) - settings_fields = new_xpansion_settings.dict(by_alias=False, exclude_none=True, exclude={"sensitivity_config"}) + settings_fields = new_xpansion_settings.model_dump( + by_alias=False, exclude_none=True, exclude={"sensitivity_config"} + ) updated_settings = actual_settings.copy(deep=True, update=settings_fields) file_study = self.study_storage_service.get_storage(study).get_raw(study) @@ -397,11 +406,11 @@ def update_xpansion_settings( msg = f"Additional constraints file '{constraints_file}' does not exist" raise XpansionFileNotFoundError(msg) from None - config_obj = updated_settings.dict(by_alias=True, exclude={"sensitivity_config"}) + config_obj = updated_settings.model_dump(by_alias=True, exclude={"sensitivity_config"}) file_study.tree.save(config_obj, ["user", "expansion", "settings"]) if new_xpansion_settings.sensitivity_config: - sensitivity_obj = new_xpansion_settings.sensitivity_config.dict(by_alias=True) + sensitivity_obj = new_xpansion_settings.sensitivity_config.model_dump(by_alias=True) file_study.tree.save(sensitivity_obj, ["user", "expansion", "sensitivity", "sensitivity_in"]) return self.get_xpansion_settings(study) @@ -541,7 +550,7 @@ def add_candidate(self, study: Study, xpansion_candidate: XpansionCandidateDTO) ) # The primary key is actually the name, the id does not matter and is never checked. logger.info(f"Adding candidate '{xpansion_candidate.name}' to study '{study.id}'") - candidates_obj[next_id] = xpansion_candidate.dict(by_alias=True, exclude_none=True) + candidates_obj[next_id] = xpansion_candidate.model_dump(by_alias=True, exclude_none=True) candidates_data = {"user": {"expansion": {"candidates": candidates_obj}}} file_study.tree.save(candidates_data) # Should we add a field in the study config containing the xpansion candidates like the links or the areas ? @@ -582,7 +591,7 @@ def update_candidate( for candidate_id, candidate in candidates.items(): if candidate["name"] == candidate_name: logger.info(f"Updating candidate '{candidate_name}' of study '{study.id}'") - candidates[candidate_id] = xpansion_candidate_dto.dict(by_alias=True, exclude_none=True) + candidates[candidate_id] = xpansion_candidate_dto.model_dump(by_alias=True, exclude_none=True) file_study.tree.save(candidates, ["user", "expansion", "candidates"]) return raise CandidateNotFoundError(f"The candidate '{xpansion_candidate_dto.name}' does not exist") @@ -602,7 +611,8 @@ def update_xpansion_constraints_settings(self, study: Study, constraints_file_na # Make sure filename is not `None`, because `None` values are ignored by the update. constraints_file_name = constraints_file_name or "" # noinspection PyArgumentList - xpansion_settings = UpdateXpansionSettings(additional_constraints=constraints_file_name) + args = {"additional_constraints": constraints_file_name} + xpansion_settings = UpdateXpansionSettings.model_validate(args) return self.update_xpansion_settings(study, xpansion_settings) def _raw_file_dir(self, raw_file_type: XpansionResourceFileType) -> t.List[str]: @@ -643,6 +653,7 @@ def _add_raw_files( content = file.file.read() if isinstance(content, str): content = content.encode(encoding="utf-8") + assert file.filename is not None buffer[file.filename] = content file_study.tree.save(data) @@ -701,17 +712,6 @@ def list_resources(self, study: Study, resource_type: XpansionResourceFileType) except ChildNotFoundError: return [] - def list_root_files(self, study: Study) -> t.List[str]: - logger.info(f"Getting xpansion root resources file from study '{study.id}'") - file_study = self.study_storage_service.get_storage(study).get_raw(study) - registered_filenames = [registered_file.key for registered_file in Expansion.registered_files] - root_files = [ - key - for key, node in t.cast(FolderNode, file_study.tree.get_node(["user", "expansion"])).build().items() - if key not in registered_filenames and not isinstance(node, BucketNode) - ] - return root_files - @staticmethod def _is_constraints_file_used(file_study: FileStudy, filename: str) -> bool: # type: ignore with contextlib.suppress(KeyError): diff --git a/antarest/study/common/__init__.py b/antarest/study/common/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/common/__init__.py +++ b/antarest/study/common/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/common/studystorage.py b/antarest/study/common/studystorage.py index 94664ef339..906564da35 100644 --- a/antarest/study/common/studystorage.py +++ b/antarest/study/common/studystorage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from abc import ABC, abstractmethod from pathlib import Path diff --git a/antarest/study/css4_colors.py b/antarest/study/css4_colors.py index 9d87c4a53e..acac63cdde 100644 --- a/antarest/study/css4_colors.py +++ b/antarest/study/css4_colors.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ CSS Color Module Level 4 diff --git a/antarest/study/main.py b/antarest/study/main.py index 83ad90dca3..1efa9cb00b 100644 --- a/antarest/study/main.py +++ b/antarest/study/main.py @@ -1,7 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI +from antarest.core.application import AppBuildContext from antarest.core.config import Config from antarest.core.filetransfer.service import FileTransferManager from antarest.core.interfaces.cache import ICache @@ -27,7 +40,7 @@ def build_study_service( - application: Optional[FastAPI], + app_ctxt: Optional[AppBuildContext], config: Config, user_service: LoginService, matrix_service: ISimpleMatrixService, @@ -112,16 +125,17 @@ def build_study_service( config=config, ) - if application: - application.include_router(create_study_routes(study_service, file_transfer_manager, config)) - application.include_router(create_raw_study_routes(study_service, config)) - application.include_router(create_study_data_routes(study_service, config)) - application.include_router( + if app_ctxt: + api_root = app_ctxt.api_root + api_root.include_router(create_study_routes(study_service, file_transfer_manager, config)) + api_root.include_router(create_raw_study_routes(study_service, config)) + api_root.include_router(create_study_data_routes(study_service, config)) + api_root.include_router( create_study_variant_routes( study_service=study_service, config=config, ) ) - application.include_router(create_xpansion_routes(study_service, config)) + api_root.include_router(create_xpansion_routes(study_service, config)) return study_service diff --git a/antarest/study/model.py b/antarest/study/model.py index 4eff8109ab..081fd48b4a 100644 --- a/antarest/study/model.py +++ b/antarest/study/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import dataclasses import enum import secrets @@ -6,7 +18,7 @@ from datetime import datetime, timedelta from pathlib import Path -from pydantic import BaseModel, validator +from pydantic import BaseModel, field_validator from sqlalchemy import ( # type: ignore Boolean, Column, @@ -339,13 +351,18 @@ class StudyMetadataDTO(BaseModel): workspace: str managed: bool archived: bool - horizon: t.Optional[str] - scenario: t.Optional[str] - status: t.Optional[str] - doc: t.Optional[str] + horizon: t.Optional[str] = None + scenario: t.Optional[str] = None + status: t.Optional[str] = None + doc: t.Optional[str] = None folder: t.Optional[str] = None tags: t.List[str] = [] + @field_validator("horizon", mode="before") + def transform_horizon_to_str(cls, val: t.Union[str, int, None]) -> t.Optional[str]: + # horizon can be an int. + return str(val) if val else val # type: ignore + class StudyMetadataPatchDTO(BaseModel): name: t.Optional[str] = None @@ -354,18 +371,20 @@ class StudyMetadataPatchDTO(BaseModel): scenario: t.Optional[str] = None status: t.Optional[str] = None doc: t.Optional[str] = None - tags: t.Sequence[str] = () + tags: t.List[str] = [] - @validator("tags", each_item=True) - def _normalize_tags(cls, v: str) -> str: + @field_validator("tags", mode="before") + def _normalize_tags(cls, v: t.List[str]) -> t.List[str]: """Remove leading and trailing whitespaces, and replace consecutive whitespaces by a single one.""" - tag = " ".join(v.split()) - if not tag: - raise ValueError("Tag cannot be empty") - elif len(tag) > 40: - raise ValueError(f"Tag is too long: {tag!r}") - else: - return tag + tags = [] + for tag in v: + tag = " ".join(tag.split()) + if not tag: + raise ValueError("Tag cannot be empty") + elif len(tag) > 40: + raise ValueError(f"Tag is too long: {tag!r}") + tags.append(tag) + return tags class StudySimSettingsDTO(BaseModel): diff --git a/antarest/study/repository.py b/antarest/study/repository.py index 4a3965d9de..f4d2e691c1 100644 --- a/antarest/study/repository.py +++ b/antarest/study/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import enum import typing as t diff --git a/antarest/study/service.py b/antarest/study/service.py index 8e4b537e19..1f8ff6a09d 100644 --- a/antarest/study/service.py +++ b/antarest/study/service.py @@ -1,9 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import base64 import collections import contextlib import http import io -import json import logging import os import time @@ -23,6 +34,7 @@ BadEditInstructionException, ChildNotFoundError, CommandApplicationError, + FileDeletionNotAllowed, IncorrectPathError, NotAManagedStudyException, ReferencedObjectDeletionNotAllowed, @@ -35,11 +47,12 @@ ) from antarest.core.filetransfer.model import FileDownloadTaskDTO from antarest.core.filetransfer.service import FileTransferManager -from antarest.core.interfaces.cache import ICache +from antarest.core.interfaces.cache import CacheConstants, ICache from antarest.core.interfaces.eventbus import Event, EventType, IEventBus from antarest.core.jwt import DEFAULT_ADMIN_USER, JWTGroup, JWTUser from antarest.core.model import JSON, SUB_JSON, PermissionInfo, PublicMode, StudyPermissionType from antarest.core.requests import RequestParameters, UserHasNotPermissionError +from antarest.core.serialization import to_json from antarest.core.tasks.model import TaskListFilter, TaskResult, TaskStatus, TaskType from antarest.core.tasks.service import ITaskService, TaskUpdateNotifier, noop_notifier from antarest.core.utils.fastapi_sqlalchemy import db @@ -118,6 +131,7 @@ from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency from antarest.study.storage.rawstudy.model.filesystem.matrix.output_series_matrix import OutputSeriesMatrix from antarest.study.storage.rawstudy.model.filesystem.raw_file_node import RawFileNode +from antarest.study.storage.rawstudy.model.filesystem.root.user.user import User from antarest.study.storage.rawstudy.raw_study_service import RawStudyService from antarest.study.storage.storage_service import StudyStorageService from antarest.study.storage.study_download_utils import StudyDownloader, get_output_variables_information @@ -1317,13 +1331,7 @@ def export_task(_notifier: TaskUpdateNotifier) -> TaskResult: return FileResponse(tmp_export_file, headers=headers, media_type=filetype) else: - json_response = json.dumps( - matrix.dict(), - ensure_ascii=False, - allow_nan=True, - indent=None, - separators=(",", ":"), - ).encode("utf-8") + json_response = to_json(matrix.model_dump()) return Response(content=json_response, media_type="application/json") def get_study_sim_result(self, study_id: str, params: RequestParameters) -> t.List[StudySimResultDTO]: @@ -1473,6 +1481,7 @@ def _create_edit_study_command( context = self.storage_service.variant_study_service.command_factory.command_context if isinstance(tree_node, IniFileNode): + assert not isinstance(data, (bytes, list)) return UpdateConfig( target=url, data=data, @@ -1488,6 +1497,7 @@ def _create_edit_study_command( matrix=matrix.tolist(), command_context=context, ) + assert isinstance(data, (list, str)) return ReplaceMatrix( target=url, matrix=data, @@ -1495,6 +1505,9 @@ def _create_edit_study_command( ) elif isinstance(tree_node, RawFileNode): if url.split("/")[-1] == "comments": + if isinstance(data, bytes): + data = data.decode("utf-8") + assert isinstance(data, str) return UpdateComments( comments=data, command_context=context, @@ -2413,7 +2426,7 @@ def unarchive_output_task( src=str(src), dest=str(dest), remove_src=not keep_src_zip, - ).dict(), + ).model_dump(), name=task_name, ref_id=study.id, request_params=params, @@ -2628,3 +2641,39 @@ def asserts_no_thermal_in_binding_constraints( if ref_bcs: binding_ids = [bc.id for bc in ref_bcs] raise ReferencedObjectDeletionNotAllowed(cluster_id, binding_ids, object_type="Cluster") + + def delete_file_or_folder(self, study_id: str, path: str, current_user: JWTUser) -> None: + """ + Deletes a file or a folder of the study. + The data must be located inside the 'User' folder. + Also, it can not be inside the 'expansion' folder. + + Args: + study_id: UUID of the concerned study + path: Path corresponding to the resource to be deleted + current_user: User that called the endpoint + + Raises: + FileDeletionNotAllowed: if the path does not comply with the above rules + """ + study = self.get_study(study_id) + assert_permission(current_user, study, StudyPermissionType.WRITE) + + url = [item for item in path.split("/") if item] + if len(url) < 2 or url[0] != "user": + raise FileDeletionNotAllowed(f"the targeted data isn't inside the 'User' folder: {path}") + + study_tree = self.storage_service.raw_study_service.get_raw(study, True).tree + user_node = t.cast(User, study_tree.get_node(["user"])) + if url[1] in [file.filename for file in user_node.registered_files]: + raise FileDeletionNotAllowed(f"you are not allowed to delete this resource : {path}") + + try: + user_node.delete(url[1:]) + except ChildNotFoundError as e: + raise FileDeletionNotAllowed("the given path doesn't exist") from e + + # update cache + cache_id = f"{CacheConstants.RAW_STUDY}/{study.id}" + updated_tree = study_tree.get() + self.storage_service.get_storage(study).cache.put(cache_id, updated_tree) # type: ignore diff --git a/antarest/study/storage/__init__.py b/antarest/study/storage/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/__init__.py +++ b/antarest/study/storage/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/abstract_storage_service.py b/antarest/study/storage/abstract_storage_service.py index 892f855970..967ece3ca6 100644 --- a/antarest/study/storage/abstract_storage_service.py +++ b/antarest/study/storage/abstract_storage_service.py @@ -1,4 +1,15 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import shutil import tempfile @@ -11,6 +22,7 @@ from antarest.core.exceptions import BadOutputError, StudyOutputNotFoundError from antarest.core.interfaces.cache import CacheConstants, ICache from antarest.core.model import JSON, PublicMode +from antarest.core.serialization import from_json from antarest.core.utils.utils import StopWatch, extract_zip, unzip, zip_dir from antarest.login.model import GroupDTO from antarest.study.common.studystorage import IStudyStorageService, T @@ -75,8 +87,7 @@ def get_study_information( additional_data = study.additional_data or StudyAdditionalData() try: - patch_obj = json.loads(additional_data.patch or "{}") - patch = Patch.parse_obj(patch_obj) + patch = Patch.model_validate(from_json(additional_data.patch or "{}")) except ValueError as e: # The conversion to JSON and the parsing can fail if the patch is not valid logger.warning(f"Failed to parse patch for study {study.id}", exc_info=e) @@ -316,7 +327,7 @@ def _read_additional_data_from_files(self, file_study: FileStudy) -> StudyAdditi horizon = file_study.tree.get(url=["settings", "generaldata", "general", "horizon"]) author = file_study.tree.get(url=["study", "antares", "author"]) patch = self.patch_service.get_from_filestudy(file_study) - study_additional_data = StudyAdditionalData(horizon=horizon, author=author, patch=patch.json()) + study_additional_data = StudyAdditionalData(horizon=horizon, author=author, patch=patch.model_dump_json()) return study_additional_data def archive_study_output(self, study: T, output_id: str) -> bool: diff --git a/antarest/study/storage/auto_archive_service.py b/antarest/study/storage/auto_archive_service.py index a1eafc40a3..85cb2237f9 100644 --- a/antarest/study/storage/auto_archive_service.py +++ b/antarest/study/storage/auto_archive_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import logging import time diff --git a/antarest/study/storage/df_download.py b/antarest/study/storage/df_download.py index 100e7f0e22..97882e2d2e 100644 --- a/antarest/study/storage/df_download.py +++ b/antarest/study/storage/df_download.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http import typing as t from pathlib import Path diff --git a/antarest/study/storage/matrix_profile.py b/antarest/study/storage/matrix_profile.py index 7dc137dc10..cd3780ae32 100644 --- a/antarest/study/storage/matrix_profile.py +++ b/antarest/study/storage/matrix_profile.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import calendar import copy import fnmatch diff --git a/antarest/study/storage/patch_service.py b/antarest/study/storage/patch_service.py index c52752ae25..1c44e1ddc9 100644 --- a/antarest/study/storage/patch_service.py +++ b/antarest/study/storage/patch_service.py @@ -1,7 +1,19 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pathlib import Path +from antarest.core.serialization import from_json from antarest.study.model import Patch, PatchOutputs, RawStudy, StudyAdditionalData from antarest.study.repository import StudyMetadataRepository from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy @@ -22,8 +34,7 @@ def get(self, study: t.Union[RawStudy, VariantStudy], get_from_file: bool = Fals if not get_from_file and study.additional_data is not None: # the `study.additional_data.patch` field is optional if study.additional_data.patch: - patch_obj = json.loads(study.additional_data.patch or "{}") - return Patch.parse_obj(patch_obj) + return Patch.model_validate(from_json(study.additional_data.patch)) patch = Patch() patch_path = Path(study.path) / PATCH_JSON @@ -55,9 +66,9 @@ def set_reference_output( def save(self, study: t.Union[RawStudy, VariantStudy], patch: Patch) -> None: if self.repository: study.additional_data = study.additional_data or StudyAdditionalData() - study.additional_data.patch = patch.json() + study.additional_data.patch = patch.model_dump_json() self.repository.save(study) patch_path = (Path(study.path)) / PATCH_JSON patch_path.parent.mkdir(parents=True, exist_ok=True) - patch_path.write_text(patch.json()) + patch_path.write_text(patch.model_dump_json()) diff --git a/antarest/study/storage/rawstudy/__init__.py b/antarest/study/storage/rawstudy/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/__init__.py +++ b/antarest/study/storage/rawstudy/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/ini_reader.py b/antarest/study/storage/rawstudy/ini_reader.py index b2d86ecb98..fd3bac2dea 100644 --- a/antarest/study/storage/rawstudy/ini_reader.py +++ b/antarest/study/storage/rawstudy/ini_reader.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import dataclasses import re import typing as t diff --git a/antarest/study/storage/rawstudy/ini_writer.py b/antarest/study/storage/rawstudy/ini_writer.py index 3a5c1198d6..f72f9b2197 100644 --- a/antarest/study/storage/rawstudy/ini_writer.py +++ b/antarest/study/storage/rawstudy/ini_writer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import ast import configparser import typing as t diff --git a/antarest/study/storage/rawstudy/model/__init__.py b/antarest/study/storage/rawstudy/model/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/__init__.py +++ b/antarest/study/storage/rawstudy/model/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py b/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py index 6106326d2f..ad10455b2e 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.core.model import JSON, SUB_JSON diff --git a/antarest/study/storage/rawstudy/model/filesystem/common/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/common/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/common/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/common/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py b/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py index 8bc1b5a497..0cff5af838 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py +++ b/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig diff --git a/antarest/study/storage/rawstudy/model/filesystem/common/prepro.py b/antarest/study/storage/rawstudy/model/filesystem/common/prepro.py index b6edf38c42..1813760f13 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/common/prepro.py +++ b/antarest/study/storage/rawstudy/model/filesystem/common/prepro.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/config/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/area.py b/antarest/study/storage/rawstudy/model/filesystem/config/area.py index 5ade25159f..74d15e5b55 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/area.py @@ -1,10 +1,22 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Object model used to read and update area configuration. """ import typing as t -from pydantic import Field, root_validator, validator +from pydantic import Field, field_validator, model_validator from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.storage.rawstudy.model.filesystem.config.field_validators import ( @@ -42,7 +54,7 @@ class OptimizationProperties(IniProperties): >>> opt = OptimizationProperties(**obj) - >>> pprint(opt.dict(by_alias=True), width=80) + >>> pprint(opt.model_dump(by_alias=True), width=80) {'filtering': {'filter-synthesis': 'hourly, daily, weekly, monthly, annual', 'filter-year-by-year': 'hourly, annual'}, 'nodal optimization': {'dispatchable-hydro-power': False, @@ -63,7 +75,7 @@ class OptimizationProperties(IniProperties): Convert the object to a dictionary for writing to a configuration file: - >>> pprint(opt.dict(by_alias=True, exclude_defaults=True), width=80) + >>> pprint(opt.model_dump(by_alias=True, exclude_defaults=True), width=80) {'filtering': {'filter-synthesis': 'hourly, weekly, monthly, annual', 'filter-year-by-year': 'hourly, monthly, annual'}, 'nodal optimization': {'dispatchable-hydro-power': False, @@ -77,7 +89,7 @@ class FilteringSection(IniProperties): filter_synthesis: str = Field("", alias="filter-synthesis") filter_year_by_year: str = Field("", alias="filter-year-by-year") - @validator("filter_synthesis", "filter_year_by_year", pre=True) + @field_validator("filter_synthesis", "filter_year_by_year", mode="before") def _validate_filtering(cls, v: t.Any) -> str: return validate_filtering(v) @@ -147,33 +159,33 @@ class AreaUI(IniProperties): ... "color_b": 255, ... } >>> ui = AreaUI(**obj) - >>> pprint(ui.dict(by_alias=True), width=80) + >>> pprint(ui.model_dump(by_alias=True), width=80) {'colorRgb': '#0080FF', 'x': 1148, 'y': 144} Update the color: >>> ui.color_rgb = (192, 168, 127) - >>> pprint(ui.dict(by_alias=True), width=80) + >>> pprint(ui.model_dump(by_alias=True), width=80) {'colorRgb': '#C0A87F', 'x': 1148, 'y': 144} """ - x: int = Field(0, description="x coordinate of the area in the map") - y: int = Field(0, description="y coordinate of the area in the map") + x: int = Field(default=0, description="x coordinate of the area in the map") + y: int = Field(default=0, description="y coordinate of the area in the map") color_rgb: str = Field( - "#E66C2C", + default="#E66C2C", alias="colorRgb", description="color of the area in the map", ) - @validator("color_rgb", pre=True) + @field_validator("color_rgb", mode="before") def _validate_color_rgb(cls, v: t.Any) -> str: return validate_color_rgb(v) - @root_validator(pre=True) + @model_validator(mode="before") def _validate_colors(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: return validate_colors(values) - def to_config(self) -> t.Mapping[str, t.Any]: + def to_config(self) -> t.Dict[str, t.Any]: """ Convert the object to a dictionary for writing to a configuration file: @@ -186,6 +198,7 @@ def to_config(self) -> t.Mapping[str, t.Any]: >>> pprint(ui.to_config(), width=80) {'color_b': 255, 'color_g': 128, 'color_r': 0, 'x': 1148, 'y': 144} """ + assert self.color_rgb is not None r = int(self.color_rgb[1:3], 16) g = int(self.color_rgb[3:5], 16) b = int(self.color_rgb[5:7], 16) @@ -204,7 +217,7 @@ class UIProperties(IniProperties): UIProperties has default values for `style` and `layers`: >>> ui = UIProperties() - >>> pprint(ui.dict(), width=80) + >>> pprint(ui.model_dump(), width=80) {'layer_styles': {0: {'color_rgb': '#E66C2C', 'x': 0, 'y': 0}}, 'layers': {0}, 'style': {'color_rgb': '#E66C2C', 'x': 0, 'y': 0}} @@ -232,7 +245,7 @@ class UIProperties(IniProperties): ... } >>> ui = UIProperties(**obj) - >>> pprint(ui.dict(), width=80) + >>> pprint(ui.model_dump(), width=80) {'layer_styles': {0: {'color_rgb': '#0080FF', 'x': 1148, 'y': 144}, 4: {'color_rgb': '#0080FF', 'x': 1148, 'y': 144}, 6: {'color_rgb': '#C0A863', 'x': 1148, 'y': 144}, @@ -248,7 +261,7 @@ class UIProperties(IniProperties): description="style of the area in the map: coordinates and color", ) layers: t.Set[int] = Field( - default_factory=set, + default_factory=lambda: {0}, description="layers where the area is visible", ) layer_styles: t.Dict[int, AreaUI] = Field( @@ -257,28 +270,20 @@ class UIProperties(IniProperties): alias="layerStyles", ) - @root_validator(pre=True) - def _set_default_style(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + @staticmethod + def _set_default_style(values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: """Defined the default style if missing.""" - style = values.get("style") + style = values.get("style", None) if style is None: values["style"] = AreaUI() elif isinstance(style, dict): values["style"] = AreaUI(**style) else: - values["style"] = AreaUI(**style.dict()) - return values - - @root_validator(pre=True) - def _set_default_layers(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: - """Define the default layers if missing.""" - _layers = values.get("layers") - if _layers is None: - values["layers"] = {0} + values["style"] = AreaUI(**style.model_dump()) return values - @root_validator(pre=True) - def _set_default_layer_styles(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + @staticmethod + def _set_default_layer_styles(values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: """Define the default layer styles if missing.""" layer_styles = values.get("layer_styles") if layer_styles is None: @@ -290,13 +295,15 @@ def _set_default_layer_styles(cls, values: t.MutableMapping[str, t.Any]) -> t.Ma if isinstance(style, dict): values["layer_styles"][key] = AreaUI(**style) else: - values["layer_styles"][key] = AreaUI(**style.dict()) + values["layer_styles"][key] = AreaUI(**style.model_dump()) else: raise TypeError(f"Invalid type for layer_styles: {type(layer_styles)}") return values - @root_validator(pre=True) + @model_validator(mode="before") def _validate_layers(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + cls._set_default_style(values) + cls._set_default_layer_styles(values) # Parse the `[ui]` section (if any) ui_section = values.pop("ui", {}) if ui_section: @@ -335,7 +342,7 @@ def _validate_layers(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str return values - def to_config(self) -> t.Mapping[str, t.Mapping[str, t.Any]]: + def to_config(self) -> t.Dict[str, t.Dict[str, t.Any]]: """ Convert the object to a dictionary for writing to a configuration file: @@ -363,7 +370,7 @@ def to_config(self) -> t.Mapping[str, t.Mapping[str, t.Any]]: 'x': 1148, 'y': 144}} """ - obj: t.MutableMapping[str, t.MutableMapping[str, t.Any]] = { + obj: t.Dict[str, t.Dict[str, t.Any]] = { "ui": {}, "layerX": {}, "layerY": {}, @@ -374,6 +381,7 @@ def to_config(self) -> t.Mapping[str, t.Mapping[str, t.Any]]: for layer, style in self.layer_styles.items(): obj["layerX"][str(layer)] = style.x obj["layerY"][str(layer)] = style.y + assert style.color_rgb is not None r = int(style.color_rgb[1:3], 16) g = int(style.color_rgb[3:5], 16) b = int(style.color_rgb[5:7], 16) @@ -393,7 +401,7 @@ class AreaFolder(IniProperties): Create and validate a new AreaProperties object from a dictionary read from a configuration file. >>> obj = AreaFolder() - >>> pprint(obj.dict(), width=80) + >>> pprint(obj.model_dump(), width=80) {'adequacy_patch': None, 'optimization': {'filtering': {'filter_synthesis': '', 'filter_year_by_year': ''}, @@ -438,7 +446,7 @@ class AreaFolder(IniProperties): ... } >>> obj = AreaFolder.construct(**data) - >>> pprint(obj.dict(), width=80) + >>> pprint(obj.model_dump(), width=80) {'adequacy_patch': None, 'optimization': {'filtering': {'filter-synthesis': 'annual, centennial'}, 'nodal optimization': {'spread-spilled-energy-cost': '15.5', @@ -500,7 +508,7 @@ class ThermalAreasProperties(IniProperties): ... }, ... } >>> area = ThermalAreasProperties(**obj) - >>> pprint(area.dict(), width=80) + >>> pprint(area.model_dump(), width=80) {'spilled_energy_cost': {'cz': 100.0}, 'unserverd_energy_cost': {'at': 4000.8, 'be': 3500.0, @@ -511,7 +519,7 @@ class ThermalAreasProperties(IniProperties): >>> area.unserverd_energy_cost["at"] = 6500.0 >>> area.unserverd_energy_cost["fr"] = 0.0 - >>> pprint(area.dict(), width=80) + >>> pprint(area.model_dump(), width=80) {'spilled_energy_cost': {'cz': 100.0}, 'unserverd_energy_cost': {'at': 6500.0, 'be': 3500.0, 'de': 1250.0, 'fr': 0.0}} @@ -534,7 +542,7 @@ class ThermalAreasProperties(IniProperties): description="spilled energy cost (€/MWh) of each area", ) - @validator("unserverd_energy_cost", "spilled_energy_cost", pre=True) + @field_validator("unserverd_energy_cost", "spilled_energy_cost", mode="before") def _validate_energy_cost(cls, v: t.Any) -> t.MutableMapping[str, float]: if isinstance(v, dict): return {str(k): float(v) for k, v in v.items()} diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py b/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py index c81d66ed5c..f902e66305 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Object model used to read and update binding constraint configuration. """ diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py b/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py index 1c84019294..62393794e2 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Common properties related to thermal and renewable clusters, and short-term storage. @@ -7,15 +19,15 @@ import functools import typing as t -from pydantic import BaseModel, Extra, Field +from pydantic import BaseModel, Field @functools.total_ordering class ItemProperties( BaseModel, - extra=Extra.forbid, + extra="forbid", validate_assignment=True, - allow_population_by_field_name=True, + populate_by_name=True, ): """ Common properties related to thermal and renewable clusters, and short-term storage. @@ -35,7 +47,7 @@ class ItemProperties( group: str = Field(default="", description="Cluster group") - name: str = Field(description="Cluster name", regex=r"[a-zA-Z0-9_(),& -]+") + name: str = Field(description="Cluster name", pattern=r"[a-zA-Z0-9_(),& -]+") def __lt__(self, other: t.Any) -> bool: """ diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/exceptions.py b/antarest/study/storage/rawstudy/model/filesystem/config/exceptions.py index 7cdf5b2a50..936f7f76e2 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/exceptions.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/exceptions.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from typing import cast diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/field_validators.py b/antarest/study/storage/rawstudy/model/filesystem/config/field_validators.py index 74f93f5c46..f6a371769b 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/field_validators.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/field_validators.py @@ -1,9 +1,21 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t _ALL_FILTERING = ["hourly", "daily", "weekly", "monthly", "annual"] -def extract_filtering(v: t.Any) -> t.Sequence[str]: +def extract_filtering(v: t.Any) -> t.List[str]: """ Extract filtering values from a comma-separated list of values. """ diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/files.py b/antarest/study/storage/rawstudy/model/filesystem/config/files.py index b8140b8c87..6cfed5b9bc 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/files.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/files.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import json import logging @@ -9,12 +21,12 @@ from pathlib import Path from antarest.core.model import JSON +from antarest.core.serialization import from_json from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( DEFAULT_GROUP, DEFAULT_OPERATOR, DEFAULT_TIMESTEP, - BindingConstraintFrequency, ) from antarest.study.storage.rawstudy.model.filesystem.config.exceptions import ( SimulationParsingError, @@ -319,7 +331,7 @@ def _parse_xpansion_version(path: Path) -> str: xpansion_json = path / "expansion" / "out.json" try: content = xpansion_json.read_text(encoding="utf-8") - obj = json.loads(content) + obj = from_json(content) return str(obj["antares_xpansion"]["version"]) except FileNotFoundError: return "" diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/identifier.py b/antarest/study/storage/rawstudy/model/filesystem/config/identifier.py index b4b1a3c3f3..2cb5d9ec64 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/identifier.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/identifier.py @@ -1,21 +1,33 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t -from pydantic import BaseModel, Extra, Field, root_validator +from pydantic import BaseModel, Field, model_validator __all__ = ("IgnoreCaseIdentifier", "LowerCaseIdentifier") class IgnoreCaseIdentifier( BaseModel, - extra=Extra.forbid, + extra="forbid", validate_assignment=True, - allow_population_by_field_name=True, + populate_by_name=True, ): """ Base class for all configuration sections with an ID. """ - id: str = Field(description="ID (section name)", regex=r"[a-zA-Z0-9_(),& -]+") + id: str = Field(description="ID (section name)", pattern=r"[a-zA-Z0-9_(),& -]+") @classmethod def generate_id(cls, name: str) -> str: @@ -33,7 +45,7 @@ def generate_id(cls, name: str) -> str: return transform_name_to_id(name, lower=False) - @root_validator(pre=True) + @model_validator(mode="before") def validate_id(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: """ Calculate an ID based on the name, if not provided. @@ -44,18 +56,21 @@ def validate_id(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.A Returns: The updated values. """ - if storage_id := values.get("id"): - # If the ID is provided, it comes from a INI section name. - # In some legacy case, the ID was in lower case, so we need to convert it. - values["id"] = cls.generate_id(storage_id) - return values - if not values.get("name"): - return values - name = values["name"] - if storage_id := cls.generate_id(name): - values["id"] = storage_id - else: - raise ValueError(f"Invalid name '{name}'.") + + # For some reason I can't explain, values can be an object. If so, no validation is needed. + if isinstance(values, dict): + if storage_id := values.get("id"): + # If the ID is provided, it comes from a INI section name. + # In some legacy case, the ID was in lower case, so we need to convert it. + values["id"] = cls.generate_id(storage_id) + return values + if not values.get("name"): + return values + name = values["name"] + if storage_id := cls.generate_id(name): + values["id"] = storage_id + else: + raise ValueError(f"Invalid name '{name}'.") return values @@ -64,7 +79,7 @@ class LowerCaseIdentifier(IgnoreCaseIdentifier): Base class for all configuration sections with a lower case ID. """ - id: str = Field(description="ID (section name)", regex=r"[a-z0-9_(),& -]+") + id: str = Field(description="ID (section name)", pattern=r"[a-z0-9_(),& -]+") @classmethod def generate_id(cls, name: str) -> str: diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/ini_properties.py b/antarest/study/storage/rawstudy/model/filesystem/config/ini_properties.py index 51f10a5ca5..e731ea203b 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/ini_properties.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/ini_properties.py @@ -1,7 +1,20 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t -from pydantic import BaseModel, Extra +from pydantic import BaseModel + +from antarest.core.serialization import from_json, to_json class IniProperties( @@ -9,17 +22,17 @@ class IniProperties( # On reading, if the configuration contains an extra field, it is better # to forbid it, because it allows errors to be detected early. # Ignoring extra attributes can hide errors. - extra=Extra.forbid, + extra="forbid", # If a field is updated on assignment, it is also validated. validate_assignment=True, # On testing, we can use snake_case for field names. - allow_population_by_field_name=True, + populate_by_name=True, ): """ Base class for configuration sections. """ - def to_config(self) -> t.Mapping[str, t.Any]: + def to_config(self) -> t.Dict[str, t.Any]: """ Convert the object to a dictionary for writing to a configuration file (`*.ini`). @@ -28,14 +41,16 @@ def to_config(self) -> t.Mapping[str, t.Any]: """ config = {} - for field_name, field in self.__fields__.items(): + for field_name, field in self.model_fields.items(): value = getattr(self, field_name) if value is None: continue + alias = field.alias + assert alias is not None if isinstance(value, IniProperties): - config[field.alias] = value.to_config() + config[alias] = value.to_config() else: - config[field.alias] = json.loads(json.dumps(value)) + config[alias] = from_json(to_json(value)) return config @classmethod @@ -44,7 +59,7 @@ def construct(cls, _fields_set: t.Optional[t.Set[str]] = None, **values: t.Any) Construct a new model instance from a dict of values, replacing aliases with real field names. """ # The pydantic construct() function does not allow aliases to be handled. - aliases = {(field.alias or name): name for name, field in cls.__fields__.items()} + aliases = {(field.alias or name): name for name, field in cls.model_fields.items()} renamed_values = {aliases.get(k, k): v for k, v in values.items()} if _fields_set is not None: _fields_set = {aliases.get(f, f) for f in _fields_set} diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/links.py b/antarest/study/storage/rawstudy/model/filesystem/config/links.py index 7ebc0e2176..88059ef50e 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/links.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/links.py @@ -1,10 +1,22 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Object model used to read and update link configuration. """ import typing as t -from pydantic import Field, root_validator, validator +from pydantic import Field, field_validator, model_validator from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.storage.rawstudy.model.filesystem.config.field_validators import ( @@ -84,7 +96,7 @@ class LinkProperties(IniProperties): >>> opt = LinkProperties(**obj) - >>> pprint(opt.dict(by_alias=True), width=80) + >>> pprint(opt.model_dump(by_alias=True), width=80) {'asset-type': , 'colorRgb': '#50C0FF', 'comments': 'This is a link', @@ -134,20 +146,20 @@ class LinkProperties(IniProperties): description="color of the area in the map", ) - @validator("filter_synthesis", "filter_year_by_year", pre=True) + @field_validator("filter_synthesis", "filter_year_by_year", mode="before") def _validate_filtering(cls, v: t.Any) -> str: return validate_filtering(v) - @validator("color_rgb", pre=True) + @field_validator("color_rgb", mode="before") def _validate_color_rgb(cls, v: t.Any) -> str: return validate_color_rgb(v) - @root_validator(pre=True) + @model_validator(mode="before") def _validate_colors(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: return validate_colors(values) # noinspection SpellCheckingInspection - def to_config(self) -> t.Mapping[str, t.Any]: + def to_config(self) -> t.Dict[str, t.Any]: """ Convert the object to a dictionary for writing to a configuration file. """ diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/model.py b/antarest/study/storage/rawstudy/model/filesystem/config/model.py index 46e02bb051..d0abd57710 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/model.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/model.py @@ -1,8 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import typing as t from pathlib import Path -from pydantic import BaseModel, Field, root_validator +from pydantic import BaseModel, Field, model_validator from antarest.core.utils.utils import DTO from antarest.study.business.enum_ignore_case import EnumIgnoreCase @@ -52,7 +64,7 @@ class Link(BaseModel, extra="ignore"): filters_synthesis: t.List[str] = Field(default_factory=list) filters_year: t.List[str] = Field(default_factory=list) - @root_validator(pre=True) + @model_validator(mode="before") def validation(cls, values: t.MutableMapping[str, t.Any]) -> t.MutableMapping[str, t.Any]: # note: field names are in kebab-case in the INI file filters_synthesis = values.pop("filter-synthesis", values.pop("filters_synthesis", "")) @@ -82,7 +94,7 @@ class DistrictSet(BaseModel): Object linked to /inputs/sets.ini information """ - ALL = ["hourly", "daily", "weekly", "monthly", "annual"] + ALL: t.List[str] = ["hourly", "daily", "weekly", "monthly", "annual"] name: t.Optional[str] = None inverted_set: bool = False areas: t.Optional[t.List[str]] = None diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py b/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py index ed0716147a..b1acfe4492 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pydantic import Field diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/ruleset_matrices.py b/antarest/study/storage/rawstudy/model/filesystem/config/ruleset_matrices.py index 5e7e380fe0..29da19c30e 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/ruleset_matrices.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/ruleset_matrices.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import numpy as np diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py b/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py index 3355ba571a..792855b141 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pydantic import Field diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py b/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py index dcd0bc7729..f3839566fd 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pydantic import Field @@ -427,4 +439,4 @@ def create_thermal_config(study_version: t.Union[str, int], **kwargs: t.Any) -> ValueError: If the study version is not supported. """ cls = get_thermal_config_cls(study_version) - return cls(**kwargs) + return cls.model_validate(kwargs) diff --git a/antarest/study/storage/rawstudy/model/filesystem/context.py b/antarest/study/storage/rawstudy/model/filesystem/context.py index 42bc9728c3..0bbb81b503 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/context.py +++ b/antarest/study/storage/rawstudy/model/filesystem/context.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from dataclasses import dataclass from antarest.matrixstore.service import ISimpleMatrixService diff --git a/antarest/study/storage/rawstudy/model/filesystem/exceptions.py b/antarest/study/storage/rawstudy/model/filesystem/exceptions.py index 4a0cdd49cd..399847efc0 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/exceptions.py +++ b/antarest/study/storage/rawstudy/model/filesystem/exceptions.py @@ -1,3 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + + class DenormalizationException(Exception): def __init__(self, msg: str): super(DenormalizationException, self).__init__(msg) diff --git a/antarest/study/storage/rawstudy/model/filesystem/factory.py b/antarest/study/storage/rawstudy/model/filesystem/factory.py index 040e747629..40b28e33d8 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/factory.py +++ b/antarest/study/storage/rawstudy/model/filesystem/factory.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import os.path import tempfile @@ -92,7 +104,7 @@ def _create_from_fs_unsafe( from_cache = self.cache.get(cache_id) if from_cache is not None: logger.info(f"Study {study_id} read from cache") - config = FileStudyTreeConfigDTO.parse_obj(from_cache).to_build_config() + config = FileStudyTreeConfigDTO.model_validate(from_cache).to_build_config() if output_path: config.output_path = output_path config.outputs = parse_outputs(output_path) @@ -106,7 +118,7 @@ def _create_from_fs_unsafe( logger.info(f"Cache new entry from StudyFactory (studyID: {study_id})") self.cache.put( cache_id, - FileStudyTreeConfigDTO.from_build_config(config).dict(), + FileStudyTreeConfigDTO.from_build_config(config).model_dump(), ) return result diff --git a/antarest/study/storage/rawstudy/model/filesystem/folder_node.py b/antarest/study/storage/rawstudy/model/filesystem/folder_node.py index ba1d859ce3..58b42a1388 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/folder_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/folder_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import shutil import typing as t from abc import ABC, abstractmethod diff --git a/antarest/study/storage/rawstudy/model/filesystem/ini_file_node.py b/antarest/study/storage/rawstudy/model/filesystem/ini_file_node.py index b2ba1c0646..bf9eecc574 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/ini_file_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/ini_file_node.py @@ -1,18 +1,30 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import functools import io -import json import logging import os import tempfile import typing as t import zipfile -from json import JSONDecodeError from pathlib import Path +import pydantic_core from filelock import FileLock from antarest.core.model import JSON, SUB_JSON +from antarest.core.serialization import from_json from antarest.study.storage.rawstudy.ini_reader import IniReader, IReader from antarest.study.storage.rawstudy.ini_writer import IniWriter from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig @@ -178,8 +190,8 @@ def save(self, data: SUB_JSON, url: t.Optional[t.List[str]] = None) -> None: info = self.reader.read(self.path) if self.path.exists() else {} obj = data if isinstance(data, str): - with contextlib.suppress(JSONDecodeError): - obj = json.loads(data) + with contextlib.suppress(pydantic_core.ValidationError): + obj = from_json(data) if len(url) == 2: if url[0] not in info: info[url[0]] = {} diff --git a/antarest/study/storage/rawstudy/model/filesystem/inode.py b/antarest/study/storage/rawstudy/model/filesystem/inode.py index e3eff7feee..e380442651 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/inode.py +++ b/antarest/study/storage/rawstudy/model/filesystem/inode.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from abc import ABC, abstractmethod from pathlib import Path from typing import Any, Dict, Generic, List, Optional, Tuple, TypeVar diff --git a/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py b/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py index e2ddfbab98..54333e2c4b 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py @@ -1,8 +1,21 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import typing as t from pathlib import Path from antarest.core.model import JSON +from antarest.core.serialization import from_json, to_json from antarest.study.storage.rawstudy.ini_reader import IReader from antarest.study.storage.rawstudy.ini_writer import IniWriter from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig @@ -35,7 +48,7 @@ def read(self, path: t.Any, **kwargs: t.Any) -> JSON: raise TypeError(repr(type(path))) try: - return t.cast(JSON, json.loads(content)) + return t.cast(JSON, from_json(content)) except json.JSONDecodeError as exc: err_msg = f"Failed to parse JSON file '{path}'" raise ValueError(err_msg) from exc @@ -47,8 +60,8 @@ class JsonWriter(IniWriter): """ def write(self, data: JSON, path: Path) -> None: - with open(path, "w") as fh: - json.dump(data, fh) + with open(path, "wb") as fh: + fh.write(to_json(data)) class JsonFileNode(IniFileNode): diff --git a/antarest/study/storage/rawstudy/model/filesystem/lazy_node.py b/antarest/study/storage/rawstudy/model/filesystem/lazy_node.py index c27b3b647f..49b83079d6 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/lazy_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/lazy_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from abc import ABC, abstractmethod from dataclasses import dataclass diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/constants.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/constants.py index 8f2b429e17..ad1300bac7 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/constants.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/constants.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy as np default_scenario_hourly = np.zeros((8760, 1), dtype=np.float64) diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py index 909140b68a..cdc67b8ac5 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re from abc import ABC, abstractmethod from typing import Hashable, List, Sequence, Tuple, cast diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/head_writer.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/head_writer.py index 5e2a899d17..5909f69ba7 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/head_writer.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/head_writer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from abc import ABC, abstractmethod diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/input_series_matrix.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/input_series_matrix.py index affaedc23e..88b7d2640a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/input_series_matrix.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/input_series_matrix.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import shutil from pathlib import Path diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/matrix.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/matrix.py index 904d57c115..364a5e3524 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/matrix.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/matrix.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from abc import ABC, abstractmethod from enum import Enum diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/output_series_matrix.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/output_series_matrix.py index 70317c6255..52c9867b2f 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/output_series_matrix.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/output_series_matrix.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from pathlib import Path from typing import Any, List, Optional, Union, cast diff --git a/antarest/study/storage/rawstudy/model/filesystem/raw_file_node.py b/antarest/study/storage/rawstudy/model/filesystem/raw_file_node.py index 57770ce02d..c92f3d9152 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/raw_file_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/raw_file_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Optional diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/desktop.py b/antarest/study/storage/rawstudy/model/filesystem/root/desktop.py index c506d2872b..20cc1b19c1 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/desktop.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/desktop.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/filestudytree.py b/antarest/study/storage/rawstudy/model/filesystem/root/filestudytree.py index e6389db280..bfef345ccc 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/filestudytree.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/filestudytree.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/areas.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/areas.py index c268e8ab2b..7dadadcc87 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/areas.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/areas.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/adequacy_patch.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/adequacy_patch.py index 6e7ac3034a..b371e886a7 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/adequacy_patch.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/adequacy_patch.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/item.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/item.py index 2a40ab60f5..37ee1d8381 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/item.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/item.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.areas.item.adequacy_patch import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/optimization.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/optimization.py index 1219a291e4..53e83b6ed2 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/optimization.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/optimization.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/ui.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/ui.py index 7a457866e2..82da8ebf64 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/ui.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/item/ui.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/list.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/list.py index 0e84498e1d..5112bd7756 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/list.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/list.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List, Optional from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/sets.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/sets.py index 1748e49def..ad327b4eeb 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/sets.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/areas/sets.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.rawstudy.ini_writer import IniWriter from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingconstraints_ini.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingconstraints_ini.py index 51e426fda2..05ce00cedf 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingconstraints_ini.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingconstraints_ini.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py index 51426d7e9e..afa55a3f17 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( OPERATOR_MATRICES_MAP, BindingConstraintFrequency, diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/prepro_series.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/prepro_series.py index b6e8f79c54..277e2311be 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/prepro_series.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/commons/prepro_series.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.common.area_matrix_list import AreaMatrixList from antarest.study.storage.rawstudy.model.filesystem.common.prepro import InputPrepro from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/allocation.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/allocation.py index b517b29a77..0714f710a5 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/allocation.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/allocation.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.hydro.allocation.area import InputHydroAllocationArea diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/area.py index 12e6d2875a..b3b89b8498 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/allocation/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/capacity.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/capacity.py index 60ebab3923..7627faa777 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/capacity.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/capacity/capacity.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List, TypedDict from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/common.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/common.py index f7b29811ff..46715ff6b7 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/common.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/common/common.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.hydro.common.capacity.capacity import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro.py index 64278ef25a..c1c3d2984a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.hydro.allocation.allocation import InputHydroAllocation diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py index 2065ea45e5..b38bafe736 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/area.py index bdce015f21..13d504d1c0 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.input_series_matrix import InputSeriesMatrix diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/prepro.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/prepro.py index 7298464e1a..560fb4cfee 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/prepro.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/area/prepro.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/prepro.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/prepro.py index b47ac54e2a..93104392f3 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/prepro.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/prepro/prepro.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.common.prepro import PreproCorrelation from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/area.py index ad7b8f0957..9488a2ffd9 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/series.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/series.py index e8ccc2e2c6..0a92743b2b 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/series.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/series/series.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.hydro.series.area.area import InputHydroSeriesArea diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py index fe22590f62..cb4c5e01b6 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import EnrModelling from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/area.py index 72d9ed3b6b..b683390565 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/capacities.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/capacities.py index ea4dd677c8..cb86c24c89 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/capacities.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/capacities/capacities.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/properties.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/properties.py index 955f6ba39d..a5ceb35fad 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/properties.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/area/properties.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/link.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/link.py index 0cb3dc3365..e12f804f9a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/link/link.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/link/link.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.link.area.area import InputLinkArea diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/miscgen.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/miscgen.py index b6d50dec4a..0590793e5c 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/miscgen.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/miscgen/miscgen.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.constants import default_8_fixed_hourly diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/clusters.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/clusters.py index 8866a46551..d1be73eff4 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/clusters.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/clusters.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/renewable.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/renewable.py index c3a0d29e87..e9b7181a19 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/renewable.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/renewable.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.renewables.clusters import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/series.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/series.py index 46b92ab5d2..cf323c311d 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/series.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/renewables/series.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/reserves.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/reserves.py index 41abcf7bf6..6c558e115c 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/reserves.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/reserves/reserves.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.constants import default_4_fixed_hourly diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/area.py index 3a4fafe18b..e77b3e16a2 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/list.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/list.py index d25d877376..05bb39ff0f 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/list.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/area/list.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/clusters.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/clusters.py index 78326277cf..ea2c055bed 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/clusters.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/clusters/clusters.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.st_storage.clusters.area.area import InputSTStorageArea diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/area.py index d9582bd2be..3a24f37dc6 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/st_storage.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/st_storage.py index 0df7979558..a531bd4bee 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/st_storage.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/area/st_storage/st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.input_series_matrix import InputSeriesMatrix diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/series.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/series.py index a724aeae5b..32aebb3351 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/series.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/series/series.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.st_storage.series.area.area import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/st_storage.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/st_storage.py index 71073518a8..b70e60381f 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/st_storage.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/st_storage/st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.st_storage.clusters.clusters import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/areas_ini.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/areas_ini.py index 024a2077b1..89747be06c 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/areas_ini.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/areas_ini.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/area.py index 2fed32670c..6fefc8ca31 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/list.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/list.py index 0349d79e35..4b4389fdfd 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/list.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/area/list.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/cluster.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/cluster.py index acf923329b..d30376d3b3 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/cluster.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/cluster/cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.thermal.cluster.area.area import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/area.py index afc70243ce..daba4ac183 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/thermal.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/thermal.py index f2ae671336..1beeb19797 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/thermal.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/area/thermal/thermal.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.input_series_matrix import InputSeriesMatrix diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/prepro.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/prepro.py index daf6fa5ffb..a9e3c19db6 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/prepro.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/prepro/prepro.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.thermal.prepro.area.area import InputThermalPreproArea diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/area.py index db10297818..33d3bf15b1 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py index c11083a882..8d765a2c16 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.constants import default_scenario_hourly diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/series.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/series.py index 28ca74fc81..44bb37d4b4 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/series.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/series.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.thermal.series.area.area import InputThermalSeriesArea diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/thermal.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/thermal.py index 8094d8f8a3..d5ee6cc7b1 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/thermal.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/thermal.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.thermal.areas_ini import InputThermalAreasIni diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/layers/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/layers/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/layers/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/layers/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/layers/layer_ini.py b/antarest/study/storage/rawstudy/model/filesystem/root/layers/layer_ini.py index 4b3fdbb85e..4755015f11 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/layers/layer_ini.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/layers/layer_ini.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/layers/layers.py b/antarest/study/storage/rawstudy/model/filesystem/root/layers/layers.py index 44a6be5baa..086475e021 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/layers/layers.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/layers/layers.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.layers.layer_ini import LayersIni diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/logs.py b/antarest/study/storage/rawstudy/model/filesystem/root/logs.py index 7e5ba868b6..f78c68d303 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/logs.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/logs.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/output.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/output.py index 75aed67f65..b45cc32c22 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/output.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/output.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/about.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/about.py index fb68676aa4..bf2ce89c37 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/about.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/about.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.raw_file_node import RawFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/study.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/study.py index ddc2670048..f0324b00fd 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/study.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/about/study.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/info_antares_output.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/info_antares_output.py index cf6fbaccd5..14e834ae0b 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/info_antares_output.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/info_antares_output.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py index 9aea14533e..0b97fa5735 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/areas.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/areas.py index 880a313dd8..5dcac4d82e 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/areas.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/areas.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/binding_const.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/binding_const.py index 822c5c8d93..662cef5af6 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/binding_const.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/binding_const.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/link.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/link.py index 7b1fdd3eb1..b5f0b15dcb 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/link.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/link.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/links.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/links.py index 1a74e89241..9d1109ee5f 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/links.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/links.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/set.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/set.py index 367edb8442..4c8a624a5c 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/set.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/set.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/utils.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/utils.py index c59a5b22b6..f8f940fd28 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/utils.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.output.simulation.mode.common.areas import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/economy.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/economy.py index c1a14e5527..a7da7fa642 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/economy.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/economy.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig, Simulation from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/grid.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/grid.py index 9a542e0c97..943de12ef2 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/grid.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcall/grid.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import pandas as pd diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/mcind.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/mcind.py index a69eaf5497..e6cac924ea 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/mcind.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/mcind/mcind.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig, Simulation from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/simulation.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/simulation.py index 629a8c937d..129b05f147 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/simulation.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/simulation.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig, Simulation from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/ts_generator.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/ts_generator.py index 8757debfd0..73e0ae6ed0 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/ts_generator.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_generator/ts_generator.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Callable from antarest.study.storage.rawstudy.model.filesystem.common.area_matrix_list import ( diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py index cc458102ca..2d5f9d729b 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.common.area_matrix_list import ( AreaMatrixList, AreaMultipleMatrixList, diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers_data.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers_data.py index 90240b04c7..670a6526ca 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers_data.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers_data.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Optional, Union diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/lp.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/lp.py index e714038ef1..da7c468535 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/lp.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/lp.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/sensitivity.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/sensitivity.py index 5a42122766..6e3e5a4ee5 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/sensitivity.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/sensitivity.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.json_file_node import JsonFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/xpansion.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/xpansion.py index faf4b1567b..9635e8be82 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/xpansion.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/xpansion/xpansion.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.json_file_node import JsonFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/generaldata.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/generaldata.py index 7bce83396b..5066bbbabd 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/generaldata.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/generaldata.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from copy import deepcopy from typing import Any, Dict diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/resources.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/resources.py index e7732f1a0d..347d90f609 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/resources.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/resources/resources.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.raw_file_node import RawFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/scenariobuilder.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/scenariobuilder.py index 8fde47960e..f80f99a942 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/scenariobuilder.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/scenariobuilder.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import typing as t diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/settings.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/settings.py index 663e62caf1..61d32f6012 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/settings.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/settings.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.raw_file_node import RawFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/simulations.py b/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/simulations.py index 0986233b96..5a8e832e11 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/simulations.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/settings/simulations/simulations.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/study_antares.py b/antarest/study/storage/rawstudy/model/filesystem/root/study_antares.py index 45bbde670a..34d83ee943 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/study_antares.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/study_antares.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/__init__.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/__init__.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/candidates.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/candidates.py index a42adb4a10..80e90ca258 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/candidates.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/candidates.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/constraint_resources.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/constraint_resources.py index 93a2846392..fdcde63d7d 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/constraint_resources.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/constraint_resources.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py index c38246f6cf..14a7a0d653 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode, RegisteredFile from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/matrix_resources.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/matrix_resources.py index 4f124d1662..a61ca899b6 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/matrix_resources.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/matrix_resources.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/sensitivity.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/sensitivity.py index f2f8c0d5bd..da42e73c64 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/sensitivity.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/sensitivity.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/settings.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/settings.py index 58dda7b433..45e568d8f6 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/settings.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/settings.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import SimpleKeyValueReader from antarest.study.storage.rawstudy.ini_writer import SimpleKeyValueWriter from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/user.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/user.py index 40a1ce7a32..5cf92d089b 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/user.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/user.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode, RegisteredFile from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer diff --git a/antarest/study/storage/rawstudy/model/helpers.py b/antarest/study/storage/rawstudy/model/helpers.py index 1987f48f4c..a8eae4e7b6 100644 --- a/antarest/study/storage/rawstudy/model/helpers.py +++ b/antarest/study/storage/rawstudy/model/helpers.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Dict, List, Optional, cast from antarest.core.model import JSON diff --git a/antarest/study/storage/rawstudy/raw_study_service.py b/antarest/study/storage/rawstudy/raw_study_service.py index 4990d70bf6..5e9295107a 100644 --- a/antarest/study/storage/rawstudy/raw_study_service.py +++ b/antarest/study/storage/rawstudy/raw_study_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import shutil import time @@ -92,7 +104,7 @@ def update_from_raw_meta(self, metadata: RawStudy, fallback_on_default: t.Option metadata.updated_at = metadata.updated_at or datetime.utcnow() if metadata.additional_data is None: metadata.additional_data = StudyAdditionalData() - metadata.additional_data.patch = metadata.additional_data.patch or Patch().json() + metadata.additional_data.patch = metadata.additional_data.patch or Patch().model_dump_json() metadata.additional_data.author = metadata.additional_data.author or "Unknown" else: diff --git a/antarest/study/storage/rawstudy/watcher.py b/antarest/study/storage/rawstudy/watcher.py index 8f593ce0d6..8b8ed98395 100644 --- a/antarest/study/storage/rawstudy/watcher.py +++ b/antarest/study/storage/rawstudy/watcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import re import tempfile diff --git a/antarest/study/storage/storage_service.py b/antarest/study/storage/storage_service.py index 599e948948..51f7555d7f 100644 --- a/antarest/study/storage/storage_service.py +++ b/antarest/study/storage/storage_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ This module provides the ``StudyStorageService`` class, which acts as a dispatcher for study storage services. It determines the appropriate study storage service based on the type of study provided. diff --git a/antarest/study/storage/study_download_utils.py b/antarest/study/storage/study_download_utils.py index 0c922fed03..9c5f6beed3 100644 --- a/antarest/study/storage/study_download_utils.py +++ b/antarest/study/storage/study_download_utils.py @@ -1,5 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import csv -import json import logging import os import re @@ -14,6 +25,7 @@ from fastapi import HTTPException from antarest.core.exceptions import ChildNotFoundError +from antarest.core.serialization import to_json from antarest.study.model import ( ExportFormat, MatrixAggregationResult, @@ -331,15 +343,8 @@ def export( target_file: Path, ) -> None: if filetype == ExportFormat.JSON: - with open(target_file, "w") as fh: - json.dump( - matrix.dict(), - fh, - ensure_ascii=False, - allow_nan=True, - indent=None, - separators=(",", ":"), - ) + with open(target_file, "wb") as fh: + fh.write(to_json(matrix.model_dump())) else: StudyDownloader.write_inside_archive(target_file, filetype, matrix) diff --git a/antarest/study/storage/study_upgrader/__init__.py b/antarest/study/storage/study_upgrader/__init__.py index c2a8427c94..e854e7d013 100644 --- a/antarest/study/storage/study_upgrader/__init__.py +++ b/antarest/study/storage/study_upgrader/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus from http.client import HTTPException from pathlib import Path diff --git a/antarest/study/storage/utils.py b/antarest/study/storage/utils.py index 5fbbf9ccb5..5d7a6c2db0 100644 --- a/antarest/study/storage/utils.py +++ b/antarest/study/storage/utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import calendar import logging import math diff --git a/antarest/study/storage/variantstudy/__init__.py b/antarest/study/storage/variantstudy/__init__.py index 8b13789179..058c6b221a 100644 --- a/antarest/study/storage/variantstudy/__init__.py +++ b/antarest/study/storage/variantstudy/__init__.py @@ -1 +1,11 @@ - +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/variantstudy/business/__init__.py b/antarest/study/storage/variantstudy/business/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/variantstudy/business/__init__.py +++ b/antarest/study/storage/variantstudy/business/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/variantstudy/business/command_extractor.py b/antarest/study/storage/variantstudy/business/command_extractor.py index 4ac5070a69..adbcc811d8 100644 --- a/antarest/study/storage/variantstudy/business/command_extractor.py +++ b/antarest/study/storage/variantstudy/business/command_extractor.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import base64 import logging import typing as t @@ -211,7 +223,7 @@ def _extract_cluster(self, study: FileStudy, area_id: str, cluster_id: str, rene create_cluster_command( area_id=area_id, cluster_name=cluster.id, - parameters=cluster.dict(by_alias=True, exclude_defaults=True, exclude={"id"}), + parameters=cluster.model_dump(by_alias=True, exclude_defaults=True, exclude={"id"}), command_context=self.command_context, ), self.generate_replace_matrix( @@ -311,6 +323,7 @@ def extract_district(self, study: FileStudy, district_id: str) -> t.List[IComman district_config = study_config.sets[district_id] base_filter = DistrictBaseFilter.add_all if district_config.inverted_set else DistrictBaseFilter.remove_all district_fetched_config = study_tree.get(["input", "areas", "sets", district_id]) + assert district_config.name is not None study_commands.append( CreateDistrict( name=district_config.name, @@ -370,7 +383,8 @@ def extract_binding_constraint( matrices[name] = matrix["data"] # Create the command to create the binding constraint - create_cmd = CreateBindingConstraint(**binding, **matrices, coeffs=terms, command_context=self.command_context) + kwargs = {**binding, **matrices, "coeffs": terms, "command_context": self.command_context} + create_cmd = CreateBindingConstraint.model_validate(kwargs) return [create_cmd] @@ -404,8 +418,8 @@ def generate_update_playlist( config = study_tree.get(["settings", "generaldata"]) playlist = get_playlist(config) return UpdatePlaylist( - items=playlist.keys() if playlist else None, - weights=({year for year, weight in playlist.items() if weight != 1} if playlist else None), + items=list(playlist.keys()) if playlist else None, + weights=({year: weight for year, weight in playlist.items() if weight != 1} if playlist else None), active=bool(playlist and len(playlist) > 0), reverse=False, command_context=self.command_context, @@ -441,6 +455,7 @@ def generate_update_district( study_tree = study.tree district_config = study_config.sets[district_id] district_fetched_config = study_tree.get(["input", "areas", "sets", district_id]) + assert district_config.name is not None return UpdateDistrict( id=district_config.name, base_filter=DistrictBaseFilter.add_all if district_config.inverted_set else DistrictBaseFilter.remove_all, diff --git a/antarest/study/storage/variantstudy/business/command_reverter.py b/antarest/study/storage/variantstudy/business/command_reverter.py index 9cf5d70b13..5134a86bea 100644 --- a/antarest/study/storage/variantstudy/business/command_reverter.py +++ b/antarest/study/storage/variantstudy/business/command_reverter.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import typing as t from pathlib import Path @@ -123,7 +135,7 @@ def _revert_update_binding_constraint( if matrix is not None: args[matrix_name] = matrix_service.get_matrix_id(matrix) - return [UpdateBindingConstraint(**args)] + return [UpdateBindingConstraint.model_validate(args)] return base_command.get_command_extractor().extract_binding_constraint(base, base_command.id) diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/__init__.py b/antarest/study/storage/variantstudy/business/matrix_constants/__init__.py index 9212a8e6c6..ae0af113f7 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/__init__.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/__init__.py @@ -1 +1,13 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from . import binding_constraint, hydro, link, prepro, st_storage, thermals diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py index 679232c20b..580794d32a 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py @@ -1 +1,13 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from . import series_after_v87, series_before_v87 # noqa: F401 diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_after_v87.py b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_after_v87.py index 30c23a7dfe..81c830f7d1 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_after_v87.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_after_v87.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy as np default_bc_hourly = np.zeros((8784, 1), dtype=np.float64) diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_before_v87.py b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_before_v87.py index f093c8e4a3..063eb069c8 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_before_v87.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_before_v87.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy as np # Matrice shapes for binding constraints are different from usual shapes, diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/common.py b/antarest/study/storage/variantstudy/business/matrix_constants/common.py index 8b6c020fe0..4507a48ce7 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/common.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/common.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List from antarest.matrixstore.model import MatrixData diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/hydro/__init__.py b/antarest/study/storage/variantstudy/business/matrix_constants/hydro/__init__.py index d205aa7510..36ac538608 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/hydro/__init__.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/hydro/__init__.py @@ -1 +1,13 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from . import v6, v7 diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v6.py b/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v6.py index c23c0e8c43..a2415c6f7e 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v6.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v6.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List from antarest.matrixstore.model import MatrixData diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v7.py b/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v7.py index 7a1aa3ddb0..0de0936333 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v7.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/hydro/v7.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List from antarest.matrixstore.model import MatrixData diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/link/__init__.py b/antarest/study/storage/variantstudy/business/matrix_constants/link/__init__.py index c7c7f46456..c517f46722 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/link/__init__.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/link/__init__.py @@ -1 +1,13 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from . import v7, v8 diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/link/v7.py b/antarest/study/storage/variantstudy/business/matrix_constants/link/v7.py index 6c91737939..4340537f99 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/link/v7.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/link/v7.py @@ -1 +1,13 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + link = [[1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] * 8760 diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/link/v8.py b/antarest/study/storage/variantstudy/business/matrix_constants/link/v8.py index 4ada31812a..839a703ef2 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/link/v8.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/link/v8.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + link = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] * 8760 direct = [[1.0]] * 8760 indirect = [[1.0]] * 8760 diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/prepro.py b/antarest/study/storage/variantstudy/business/matrix_constants/prepro.py index bf1c5124ea..2a04905c67 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/prepro.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/prepro.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + conversion = [ [-9999999980506447872.0, 0.0, 9999999980506447872.0], [0.0, 0.0, 0.0], diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/__init__.py b/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/__init__.py index 0a1b9046e5..f6c48f1942 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/__init__.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/__init__.py @@ -1 +1,13 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from . import series diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/series.py b/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/series.py index 90d705b7e8..5efba8eece 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/series.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/st_storage/series.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy as np pmax_injection = np.ones((8760, 1), dtype=np.float64) diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/thermals/__init__.py b/antarest/study/storage/variantstudy/business/matrix_constants/thermals/__init__.py index 39933eb2e1..1b665aa933 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/thermals/__init__.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/thermals/__init__.py @@ -1 +1,13 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from . import prepro diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/thermals/prepro.py b/antarest/study/storage/variantstudy/business/matrix_constants/thermals/prepro.py index eb0d3c9160..d244f5e7b4 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/thermals/prepro.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/thermals/prepro.py @@ -1,2 +1,14 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + data = [[1.0, 1.0, 0.0, 0.0, 0.0, 0.0]] * 365 modulation = [[1.0, 1.0, 1.0, 0.0]] * 8760 diff --git a/antarest/study/storage/variantstudy/business/matrix_constants_generator.py b/antarest/study/storage/variantstudy/business/matrix_constants_generator.py index 4c75f6a6eb..abb0953b4c 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants_generator.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants_generator.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import tempfile from pathlib import Path from typing import Dict diff --git a/antarest/study/storage/variantstudy/business/utils.py b/antarest/study/storage/variantstudy/business/utils.py index 75396ccbc6..9f1988d1de 100644 --- a/antarest/study/storage/variantstudy/business/utils.py +++ b/antarest/study/storage/variantstudy/business/utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.core.model import JSON diff --git a/antarest/study/storage/variantstudy/business/utils_binding_constraint.py b/antarest/study/storage/variantstudy/business/utils_binding_constraint.py index 8d7464c5aa..328e43f0f6 100644 --- a/antarest/study/storage/variantstudy/business/utils_binding_constraint.py +++ b/antarest/study/storage/variantstudy/business/utils_binding_constraint.py @@ -1,7 +1,18 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( - DEFAULT_TIMESTEP, BindingConstraintFrequency, BindingConstraintOperator, ) diff --git a/antarest/study/storage/variantstudy/command_factory.py b/antarest/study/storage/variantstudy/command_factory.py index 45d325585b..409cf81bb5 100644 --- a/antarest/study/storage/variantstudy/command_factory.py +++ b/antarest/study/storage/variantstudy/command_factory.py @@ -1,3 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +import copy import typing as t from antarest.core.model import JSON @@ -105,10 +118,15 @@ def to_command(self, command_dto: CommandDTO) -> t.List[ICommand]: """ args = command_dto.args if isinstance(args, dict): - return [self._to_single_command(command_dto.action, args, command_dto.version, command_dto.id)] + # In some cases, pydantic can modify inplace the given args. + # We don't want that so before doing so we copy the dictionnary. + new_args = copy.deepcopy(args) + return [self._to_single_command(command_dto.action, new_args, command_dto.version, command_dto.id)] elif isinstance(args, list): return [ - self._to_single_command(command_dto.action, argument, command_dto.version, command_dto.id) + self._to_single_command( + command_dto.action, copy.deepcopy(argument), command_dto.version, command_dto.id + ) for argument in args ] raise NotImplementedError() diff --git a/antarest/study/storage/variantstudy/model/__init__.py b/antarest/study/storage/variantstudy/model/__init__.py index 8b13789179..058c6b221a 100644 --- a/antarest/study/storage/variantstudy/model/__init__.py +++ b/antarest/study/storage/variantstudy/model/__init__.py @@ -1 +1,11 @@ - +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/variantstudy/model/command/__init__.py b/antarest/study/storage/variantstudy/model/command/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/storage/variantstudy/model/command/__init__.py +++ b/antarest/study/storage/variantstudy/model/command/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/storage/variantstudy/model/command/common.py b/antarest/study/storage/variantstudy/model/command/common.py index 9410ef20e6..dc5dce4331 100644 --- a/antarest/study/storage/variantstudy/model/command/common.py +++ b/antarest/study/storage/variantstudy/model/command/common.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from dataclasses import dataclass from enum import Enum diff --git a/antarest/study/storage/variantstudy/model/command/create_area.py b/antarest/study/storage/variantstudy/model/command/create_area.py index 0ef68b61d3..bfc8711b8e 100644 --- a/antarest/study/storage/variantstudy/model/command/create_area.py +++ b/antarest/study/storage/variantstudy/model/command/create_area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pydantic import Field @@ -49,8 +61,8 @@ class CreateArea(ICommand): # Overloaded metadata # =================== - command_name = CommandName.CREATE_AREA - version = 1 + command_name: CommandName = CommandName.CREATE_AREA + version: int = 1 # Command parameters # ================== diff --git a/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py b/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py index e917a48850..5d425332c3 100644 --- a/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py +++ b/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py @@ -1,13 +1,24 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from abc import ABCMeta from enum import Enum import numpy as np -from pydantic import BaseModel, Extra, Field, root_validator, validator +from pydantic import BaseModel, Field, field_validator, model_validator from antarest.matrixstore.model import MatrixData -from antarest.study.business.all_optional_meta import AllOptionalMetaclass +from antarest.study.business.all_optional_meta import all_optional_model, camel_case_model from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( DEFAULT_GROUP, DEFAULT_OPERATOR, @@ -79,26 +90,24 @@ def check_matrix_values(time_step: BindingConstraintFrequency, values: MatrixTyp # ================================================================================= -class BindingConstraintPropertiesBase(BaseModel, extra=Extra.forbid, allow_population_by_field_name=True): +class BindingConstraintPropertiesBase(BaseModel, extra="forbid", populate_by_name=True): enabled: bool = True time_step: BindingConstraintFrequency = Field(DEFAULT_TIMESTEP, alias="type") operator: BindingConstraintOperator = DEFAULT_OPERATOR comments: str = "" - @classmethod - def from_dict(cls, **attrs: t.Any) -> "BindingConstraintPropertiesBase": - """ - Instantiate a class from a dictionary excluding unknown or `None` fields. - """ - attrs = {k: v for k, v in attrs.items() if k in cls.__fields__ and v is not None} - return cls(**attrs) + @model_validator(mode="before") + def replace_with_alias(cls, values: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + if "type" in values: + values["time_step"] = values.pop("type") + return values class BindingConstraintProperties830(BindingConstraintPropertiesBase): filter_year_by_year: str = Field("", alias="filter-year-by-year") filter_synthesis: str = Field("", alias="filter-synthesis") - @validator("filter_synthesis", "filter_year_by_year", pre=True) + @field_validator("filter_synthesis", "filter_year_by_year", mode="before") def _validate_filtering(cls, v: t.Any) -> str: return validate_filtering(v) @@ -139,10 +148,12 @@ def create_binding_constraint_config(study_version: t.Union[str, int], **kwargs: The binding_constraint configuration model. """ cls = get_binding_constraint_config_cls(study_version) - return cls.from_dict(**kwargs) + attrs = {k: v for k, v in kwargs.items() if k in cls.model_fields and v is not None} + return cls(**attrs) -class OptionalProperties(BindingConstraintProperties870, metaclass=AllOptionalMetaclass, use_none=True): +@all_optional_model +class OptionalProperties(BindingConstraintProperties870): pass @@ -151,32 +162,30 @@ class OptionalProperties(BindingConstraintProperties870, metaclass=AllOptionalMe # ================================================================================= -class BindingConstraintMatrices(BaseModel, extra=Extra.forbid, allow_population_by_field_name=True): +@camel_case_model +class BindingConstraintMatrices(BaseModel, extra="forbid", populate_by_name=True): """ Class used to store the matrices of a binding constraint. """ values: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="2nd member matrix for studies before v8.7", ) less_term_matrix: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="less term matrix for v8.7+ studies", - alias="lessTermMatrix", ) greater_term_matrix: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="greater term matrix for v8.7+ studies", - alias="greaterTermMatrix", ) equal_term_matrix: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="equal term matrix for v8.7+ studies", - alias="equalTermMatrix", ) - @root_validator(pre=True) + @model_validator(mode="before") def check_matrices( cls, values: t.Dict[str, t.Optional[t.Union[MatrixType, str]]] ) -> t.Dict[str, t.Optional[t.Union[MatrixType, str]]]: @@ -203,10 +212,10 @@ class AbstractBindingConstraintCommand(OptionalProperties, BindingConstraintMatr Abstract class for binding constraint commands. """ - coeffs: t.Optional[t.Dict[str, t.List[float]]] + coeffs: t.Optional[t.Dict[str, t.List[float]]] = None def to_dto(self) -> CommandDTO: - json_command = json.loads(self.json(exclude={"command_context"})) + json_command = self.model_dump(mode="json", exclude={"command_context"}) args = {} for field in ["enabled", "coeffs", "comments", "time_step", "operator"]: if json_command[field]: @@ -389,7 +398,7 @@ class CreateBindingConstraint(AbstractBindingConstraintCommand): Command used to create a binding constraint. """ - command_name = CommandName.CREATE_BINDING_CONSTRAINT + command_name: CommandName = CommandName.CREATE_BINDING_CONSTRAINT version: int = 1 # Properties of the `CREATE_BINDING_CONSTRAINT` command: @@ -416,8 +425,8 @@ def _apply(self, study_data: FileStudy) -> CommandOutput: bd_id = transform_name_to_id(self.name) study_version = study_data.config.version - props = create_binding_constraint_config(study_version, **self.dict()) - obj = json.loads(props.json(by_alias=True)) + props = create_binding_constraint_config(study_version, **self.model_dump()) + obj = props.model_dump(mode="json", by_alias=True) new_binding = {"id": bd_id, "name": self.name, **obj} @@ -443,9 +452,9 @@ def _create_diff(self, other: "ICommand") -> t.List["ICommand"]: bd_id = transform_name_to_id(self.name) args = {"id": bd_id, "command_context": other.command_context} - excluded_fields = frozenset(ICommand.__fields__) - self_command = json.loads(self.json(exclude=excluded_fields)) - other_command = json.loads(other.json(exclude=excluded_fields)) + excluded_fields = set(ICommand.model_fields) + self_command = self.model_dump(mode="json", exclude=excluded_fields) + other_command = other.model_dump(mode="json", exclude=excluded_fields) properties = [ "enabled", "coeffs", @@ -469,7 +478,7 @@ def _create_diff(self, other: "ICommand") -> t.List["ICommand"]: if self_matrix_id != other_matrix_id: args[matrix_name] = other_matrix_id - return [UpdateBindingConstraint(**args)] + return [UpdateBindingConstraint.model_validate(args)] def match(self, other: "ICommand", equal: bool = False) -> bool: if not isinstance(other, self.__class__): diff --git a/antarest/study/storage/variantstudy/model/command/create_cluster.py b/antarest/study/storage/variantstudy/model/command/create_cluster.py index a884eb7b9c..a1c6ef17aa 100644 --- a/antarest/study/storage/variantstudy/model/command/create_cluster.py +++ b/antarest/study/storage/variantstudy/model/command/create_cluster.py @@ -1,6 +1,18 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t -from pydantic import validator +from pydantic import Field, ValidationInfo, field_validator from antarest.core.model import JSON from antarest.core.utils.utils import assert_this @@ -26,46 +38,51 @@ class CreateCluster(ICommand): # Overloaded metadata # =================== - command_name = CommandName.CREATE_THERMAL_CLUSTER - version = 1 + command_name: CommandName = CommandName.CREATE_THERMAL_CLUSTER + version: int = 1 # Command parameters # ================== area_id: str cluster_name: str - parameters: t.Dict[str, str] - prepro: t.Optional[t.Union[t.List[t.List[MatrixData]], str]] = None - modulation: t.Optional[t.Union[t.List[t.List[MatrixData]], str]] = None + parameters: t.Dict[str, t.Any] + prepro: t.Optional[t.Union[t.List[t.List[MatrixData]], str]] = Field(None, validate_default=True) + modulation: t.Optional[t.Union[t.List[t.List[MatrixData]], str]] = Field(None, validate_default=True) - @validator("cluster_name") + @field_validator("cluster_name", mode="before") def validate_cluster_name(cls, val: str) -> str: valid_name = transform_name_to_id(val, lower=False) if valid_name != val: raise ValueError("Cluster name must only contains [a-zA-Z0-9],&,-,_,(,) characters") return val - @validator("prepro", always=True) + @field_validator("prepro", mode="before") def validate_prepro( - cls, v: t.Optional[t.Union[t.List[t.List[MatrixData]], str]], values: t.Any + cls, + v: t.Optional[t.Union[t.List[t.List[MatrixData]], str]], + values: t.Union[t.Dict[str, t.Any], ValidationInfo], ) -> t.Optional[t.Union[t.List[t.List[MatrixData]], str]]: + new_values = values if isinstance(values, dict) else values.data if v is None: - v = values["command_context"].generator_matrix_constants.get_thermal_prepro_data() + v = new_values["command_context"].generator_matrix_constants.get_thermal_prepro_data() return v - else: - return validate_matrix(v, values) + return validate_matrix(v, new_values) - @validator("modulation", always=True) + @field_validator("modulation", mode="before") def validate_modulation( - cls, v: t.Optional[t.Union[t.List[t.List[MatrixData]], str]], values: t.Any + cls, + v: t.Optional[t.Union[t.List[t.List[MatrixData]], str]], + values: t.Union[t.Dict[str, t.Any], ValidationInfo], ) -> t.Optional[t.Union[t.List[t.List[MatrixData]], str]]: + new_values = values if isinstance(values, dict) else values.data if v is None: - v = values["command_context"].generator_matrix_constants.get_thermal_prepro_modulation() + v = new_values["command_context"].generator_matrix_constants.get_thermal_prepro_modulation() return v else: - return validate_matrix(v, values) + return validate_matrix(v, new_values) def _apply_config(self, study_data: FileStudyTreeConfig) -> t.Tuple[CommandOutput, t.Dict[str, t.Any]]: # Search the Area in the configuration diff --git a/antarest/study/storage/variantstudy/model/command/create_district.py b/antarest/study/storage/variantstudy/model/command/create_district.py index 9311345db0..afb9736806 100644 --- a/antarest/study/storage/variantstudy/model/command/create_district.py +++ b/antarest/study/storage/variantstudy/model/command/create_district.py @@ -1,7 +1,19 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from enum import Enum from typing import Any, Dict, List, Optional, Tuple, cast -from pydantic import validator +from pydantic import field_validator from antarest.study.storage.rawstudy.model.filesystem.config.model import ( DistrictSet, @@ -27,8 +39,8 @@ class CreateDistrict(ICommand): # Overloaded metadata # =================== - command_name = CommandName.CREATE_DISTRICT - version = 1 + command_name: CommandName = CommandName.CREATE_DISTRICT + version: int = 1 # Command parameters # ================== @@ -39,7 +51,7 @@ class CreateDistrict(ICommand): output: bool = True comments: str = "" - @validator("name") + @field_validator("name") def validate_district_name(cls, val: str) -> str: valid_name = transform_name_to_id(val, lower=False) if valid_name != val: diff --git a/antarest/study/storage/variantstudy/model/command/create_link.py b/antarest/study/storage/variantstudy/model/command/create_link.py index f716b0c4d6..ef2d21f0a9 100644 --- a/antarest/study/storage/variantstudy/model/command/create_link.py +++ b/antarest/study/storage/variantstudy/model/command/create_link.py @@ -1,6 +1,18 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict, List, Optional, Tuple, Union, cast -from pydantic import root_validator, validator +from pydantic import ValidationInfo, field_validator, model_validator from antarest.core.model import JSON from antarest.core.utils.utils import assert_this @@ -39,30 +51,31 @@ class CreateLink(ICommand): # Overloaded metadata # =================== - command_name = CommandName.CREATE_LINK - version = 1 + command_name: CommandName = CommandName.CREATE_LINK + version: int = 1 # Command parameters # ================== area1: str area2: str - parameters: Optional[Dict[str, str]] = None + parameters: Optional[Dict[str, Any]] = None series: Optional[Union[List[List[MatrixData]], str]] = None direct: Optional[Union[List[List[MatrixData]], str]] = None indirect: Optional[Union[List[List[MatrixData]], str]] = None - @validator("series", "direct", "indirect", always=True) + @field_validator("series", "direct", "indirect", mode="before") def validate_series( - cls, v: Optional[Union[List[List[MatrixData]], str]], values: Any + cls, v: Optional[Union[List[List[MatrixData]], str]], values: Union[Dict[str, Any], ValidationInfo] ) -> Optional[Union[List[List[MatrixData]], str]]: - return validate_matrix(v, values) if v is not None else v + new_values = values if isinstance(values, dict) else values.data + return validate_matrix(v, new_values) if v is not None else v - @root_validator - def validate_areas(cls, values: Dict[str, Any]) -> Any: - if values.get("area1") == values.get("area2"): + @model_validator(mode="after") + def validate_areas(self) -> "CreateLink": + if self.area1 == self.area2: raise ValueError("Cannot create link on same node") - return values + return self def _create_link_in_config(self, area_from: str, area_to: str, study_data: FileStudyTreeConfig) -> None: self.parameters = self.parameters or {} diff --git a/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py b/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py index c0c9aa44f8..1a932dd30d 100644 --- a/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py +++ b/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py @@ -1,6 +1,18 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t -from pydantic import validator +from pydantic import field_validator from antarest.core.model import JSON from antarest.study.storage.rawstudy.model.filesystem.config.model import ( @@ -24,17 +36,17 @@ class CreateRenewablesCluster(ICommand): # Overloaded metadata # =================== - command_name = CommandName.CREATE_RENEWABLES_CLUSTER - version = 1 + command_name: CommandName = CommandName.CREATE_RENEWABLES_CLUSTER + version: int = 1 # Command parameters # ================== area_id: str cluster_name: str - parameters: t.Dict[str, str] + parameters: t.Dict[str, t.Any] - @validator("cluster_name") + @field_validator("cluster_name") def validate_cluster_name(cls, val: str) -> str: valid_name = transform_name_to_id(val, lower=False) if valid_name != val: diff --git a/antarest/study/storage/variantstudy/model/command/create_st_storage.py b/antarest/study/storage/variantstudy/model/command/create_st_storage.py index 90fb980c4b..8244957da5 100644 --- a/antarest/study/storage/variantstudy/model/command/create_st_storage.py +++ b/antarest/study/storage/variantstudy/model/command/create_st_storage.py @@ -1,9 +1,19 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import numpy as np -from pydantic import Field, validator -from pydantic.fields import ModelField +from pydantic import Field, ValidationInfo, model_validator from antarest.core.model import JSON from antarest.matrixstore.model import MatrixData @@ -40,32 +50,32 @@ class CreateSTStorage(ICommand): # Overloaded metadata # =================== - command_name = CommandName.CREATE_ST_STORAGE - version = 1 + command_name: CommandName = CommandName.CREATE_ST_STORAGE + version: int = 1 # Command parameters # ================== - area_id: str = Field(description="Area ID", regex=r"[a-z0-9_(),& -]+") + area_id: str = Field(description="Area ID", pattern=r"[a-z0-9_(),& -]+") parameters: STStorageConfigType pmax_injection: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="Charge capacity (modulation)", ) pmax_withdrawal: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="Discharge capacity (modulation)", ) lower_rule_curve: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="Lower rule curve (coefficient)", ) upper_rule_curve: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="Upper rule curve (coefficient)", ) inflows: t.Optional[t.Union[MatrixType, str]] = Field( - None, + default=None, description="Inflows (MW)", ) @@ -79,12 +89,9 @@ def storage_name(self) -> str: """The label representing the name of the storage for the user.""" return self.parameters.name - @validator(*_MATRIX_NAMES, always=True) - def register_matrix( - cls, - v: t.Optional[t.Union[MatrixType, str]], - values: t.Dict[str, t.Any], - field: ModelField, + @staticmethod + def validate_field( + v: t.Optional[t.Union[MatrixType, str]], values: t.Dict[str, t.Any], field: str ) -> t.Optional[t.Union[MatrixType, str]]: """ Validates a matrix array or link, and store the matrix array in the matrix repository. @@ -100,7 +107,7 @@ def register_matrix( Args: v: The matrix array or link to be validated and registered. values: A dictionary containing additional values used for validation. - field: The field being validated. + field: The name of the validated parameter Returns: The ID of the validated and stored matrix prefixed by "matrix://". @@ -122,7 +129,7 @@ def register_matrix( "upper_rule_curve": constants.get_st_storage_upper_rule_curve, "inflows": constants.get_st_storage_inflows, } - method = methods[field.name] + method = methods[field] return method() if isinstance(v, str): # Check the matrix link @@ -136,7 +143,7 @@ def register_matrix( raise ValueError("Matrix values cannot contain NaN") # All matrices except "inflows" are constrained between 0 and 1 constrained = set(_MATRIX_NAMES) - {"inflows"} - if field.name in constrained and (np.any(array < 0) or np.any(array > 1)): + if field in constrained and (np.any(array < 0) or np.any(array > 1)): raise ValueError("Matrix values should be between 0 and 1") v = t.cast(MatrixType, array.tolist()) return validate_matrix(v, values) @@ -144,6 +151,13 @@ def register_matrix( # pragma: no cover raise TypeError(repr(v)) + @model_validator(mode="before") + def validate_matrices(cls, values: t.Union[t.Dict[str, t.Any], ValidationInfo]) -> t.Dict[str, t.Any]: + new_values = values if isinstance(values, dict) else values.data + for field in _MATRIX_NAMES: + new_values[field] = cls.validate_field(new_values.get(field, None), new_values, field) + return new_values + def _apply_config(self, study_data: FileStudyTreeConfig) -> t.Tuple[CommandOutput, t.Dict[str, t.Any]]: """ Applies configuration changes to the study data: add the short-term storage in the storages list. @@ -211,14 +225,14 @@ def _apply(self, study_data: FileStudy) -> CommandOutput: Returns: The output of the command execution. """ - output, data = self._apply_config(study_data.config) + output, _ = self._apply_config(study_data.config) if not output.status: return output # Fill-in the "list.ini" file with the parameters. # On creation, it's better to write all the parameters in the file. config = study_data.tree.get(["input", "st-storage", "clusters", self.area_id, "list"]) - config[self.storage_id] = json.loads(self.parameters.json(by_alias=True, exclude={"id"})) + config[self.storage_id] = self.parameters.model_dump(mode="json", by_alias=True, exclude={"id"}) new_data: JSON = { "input": { @@ -240,7 +254,7 @@ def to_dto(self) -> CommandDTO: Returns: The DTO object representing the current command. """ - parameters = json.loads(self.parameters.json(by_alias=True, exclude={"id"})) + parameters = self.parameters.model_dump(mode="json", by_alias=True, exclude={"id"}) return CommandDTO( action=self.command_name.value, args={ @@ -305,7 +319,7 @@ def _create_diff(self, other: "ICommand") -> t.List["ICommand"]: if getattr(self, attr) != getattr(other, attr) ] if self.parameters != other.parameters: - data: t.Dict[str, t.Any] = json.loads(other.parameters.json(by_alias=True, exclude={"id"})) + data: t.Dict[str, t.Any] = other.parameters.model_dump(mode="json", by_alias=True, exclude={"id"}) commands.append( UpdateConfig( target=f"input/st-storage/clusters/{self.area_id}/list/{self.storage_id}", diff --git a/antarest/study/storage/variantstudy/model/command/generate_thermal_cluster_timeseries.py b/antarest/study/storage/variantstudy/model/command/generate_thermal_cluster_timeseries.py index c604e9d6e0..ad7e5fa863 100644 --- a/antarest/study/storage/variantstudy/model/command/generate_thermal_cluster_timeseries.py +++ b/antarest/study/storage/variantstudy/model/command/generate_thermal_cluster_timeseries.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import shutil import tempfile @@ -31,8 +43,8 @@ class GenerateThermalClusterTimeSeries(ICommand): Command used to generate thermal cluster timeseries for an entire study """ - command_name = CommandName.GENERATE_THERMAL_CLUSTER_TIMESERIES - version = 1 + command_name: CommandName = CommandName.GENERATE_THERMAL_CLUSTER_TIMESERIES + version: int = 1 def _apply_config(self, study_data: FileStudyTreeConfig) -> OutputTuple: return CommandOutput(status=True, message="Nothing to do"), {} diff --git a/antarest/study/storage/variantstudy/model/command/icommand.py b/antarest/study/storage/variantstudy/model/command/icommand.py index 98b8756dda..eb9a1f1285 100644 --- a/antarest/study/storage/variantstudy/model/command/icommand.py +++ b/antarest/study/storage/variantstudy/model/command/icommand.py @@ -1,10 +1,22 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import typing as t import uuid from abc import ABC, abstractmethod import typing_extensions as te -from pydantic import BaseModel, Extra +from pydantic import BaseModel from antarest.core.utils.utils import assert_this from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig @@ -23,7 +35,7 @@ OutputTuple: te.TypeAlias = t.Tuple[CommandOutput, t.Dict[str, t.Any]] -class ICommand(ABC, BaseModel, extra=Extra.forbid, arbitrary_types_allowed=True, copy_on_model_validation="deep"): +class ICommand(ABC, BaseModel, extra="forbid", arbitrary_types_allowed=True): """ Interface for all commands that can be applied to a study. @@ -126,9 +138,9 @@ def match(self, other: "ICommand", equal: bool = False) -> bool: """ if not isinstance(other, self.__class__): return False - excluded_fields = set(ICommand.__fields__) - this_values = self.dict(exclude=excluded_fields) - that_values = other.dict(exclude=excluded_fields) + excluded_fields = set(ICommand.model_fields) + this_values = self.model_dump(exclude=excluded_fields) + that_values = other.model_dump(exclude=excluded_fields) return this_values == that_values @abstractmethod diff --git a/antarest/study/storage/variantstudy/model/command/remove_area.py b/antarest/study/storage/variantstudy/model/command/remove_area.py index f39c8aac9c..3bf3e1856c 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_area.py +++ b/antarest/study/storage/variantstudy/model/command/remove_area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import logging import typing as t @@ -21,7 +33,7 @@ class RemoveArea(ICommand): Command used to remove an area. """ - command_name = CommandName.REMOVE_AREA + command_name: CommandName = CommandName.REMOVE_AREA version: int = 1 # Properties of the `REMOVE_AREA` command: diff --git a/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py b/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py index d2bd4de9ea..ee51c7e641 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py +++ b/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict, List, Tuple from antarest.core.model import JSON @@ -15,7 +27,7 @@ class RemoveBindingConstraint(ICommand): Command used to remove a binding constraint. """ - command_name = CommandName.REMOVE_BINDING_CONSTRAINT + command_name: CommandName = CommandName.REMOVE_BINDING_CONSTRAINT version: int = 1 # Properties of the `REMOVE_BINDING_CONSTRAINT` command: diff --git a/antarest/study/storage/variantstudy/model/command/remove_cluster.py b/antarest/study/storage/variantstudy/model/command/remove_cluster.py index a9460f4025..3895b423e9 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_cluster.py +++ b/antarest/study/storage/variantstudy/model/command/remove_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.study.storage.rawstudy.model.filesystem.config.model import Area, FileStudyTreeConfig @@ -18,8 +30,8 @@ class RemoveCluster(ICommand): # Overloaded metadata # =================== - command_name = CommandName.REMOVE_THERMAL_CLUSTER - version = 1 + command_name: CommandName = CommandName.REMOVE_THERMAL_CLUSTER + version: int = 1 # Command parameters # ================== @@ -175,7 +187,7 @@ def _remove_cluster_from_binding_constraints(self, study_data: FileStudy) -> Non # Collect the binding constraints that are related to the area to remove # by searching the terms that contain the ID of the area. - bc_to_remove = {} + bc_to_remove = [] lower_area_id = self.area_id.lower() lower_cluster_id = self.cluster_id.lower() for bc_index, bc in list(binding_constraints.items()): @@ -188,16 +200,15 @@ def _remove_cluster_from_binding_constraints(self, study_data: FileStudy) -> Non # noinspection PyTypeChecker related_area_id, related_cluster_id = map(str.lower, key.split(".")) if (lower_area_id, lower_cluster_id) == (related_area_id, related_cluster_id): - bc_to_remove[bc_index] = binding_constraints.pop(bc_index) + bc_to_remove.append(binding_constraints.pop(bc_index)["id"]) break matrix_suffixes = ["_lt", "_gt", "_eq"] if study_data.config.version >= 870 else [""] existing_files = study_data.tree.get(["input", "bindingconstraints"], depth=1) - for bc_index, bc in bc_to_remove.items(): - for suffix in matrix_suffixes: - matrix_id = f"{bc['id']}{suffix}" - if matrix_id in existing_files: - study_data.tree.delete(["input", "bindingconstraints", matrix_id]) + for bc_id, suffix in zip(bc_to_remove, matrix_suffixes): + matrix_id = f"{bc_id}{suffix}" + if matrix_id in existing_files: + study_data.tree.delete(["input", "bindingconstraints", matrix_id]) study_data.tree.save(binding_constraints, url) diff --git a/antarest/study/storage/variantstudy/model/command/remove_district.py b/antarest/study/storage/variantstudy/model/command/remove_district.py index 36995b5c11..586a827943 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_district.py +++ b/antarest/study/storage/variantstudy/model/command/remove_district.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict, List, Tuple from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig @@ -15,8 +27,8 @@ class RemoveDistrict(ICommand): # Overloaded metadata # =================== - command_name = CommandName.REMOVE_DISTRICT - version = 1 + command_name: CommandName = CommandName.REMOVE_DISTRICT + version: int = 1 # Command parameters # ================== diff --git a/antarest/study/storage/variantstudy/model/command/remove_link.py b/antarest/study/storage/variantstudy/model/command/remove_link.py index c82597f32b..a384ccff58 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_link.py +++ b/antarest/study/storage/variantstudy/model/command/remove_link.py @@ -1,6 +1,18 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t -from pydantic import root_validator, validator +from pydantic import field_validator, model_validator from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig, transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy @@ -17,7 +29,7 @@ class RemoveLink(ICommand): # Overloaded metadata # =================== - command_name = CommandName.REMOVE_LINK + command_name: CommandName = CommandName.REMOVE_LINK version: int = 1 # Command parameters @@ -28,7 +40,7 @@ class RemoveLink(ICommand): area2: str # noinspection PyMethodParameters - @validator("area1", "area2", pre=True) + @field_validator("area1", "area2", mode="before") def _validate_id(cls, area: str) -> str: if isinstance(area, str): # Area IDs must be in lowercase and not empty. @@ -42,16 +54,12 @@ def _validate_id(cls, area: str) -> str: return area # noinspection PyMethodParameters - @root_validator(pre=False) - def _validate_link(cls, values: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: - area1 = values.get("area1") - area2 = values.get("area2") - - if area1 and area2: - # By convention, the source area is always the smallest one (in lexicographic order). - values["area1"], values["area2"] = sorted([area1, area2]) - - return values + @model_validator(mode="after") + def _validate_link(self) -> "RemoveLink": + # By convention, the source area is always the smallest one (in lexicographic order). + if self.area1 > self.area2: + self.area1, self.area2 = self.area2, self.area1 + return self def _check_link_exists(self, study_cfg: FileStudyTreeConfig) -> OutputTuple: """ diff --git a/antarest/study/storage/variantstudy/model/command/remove_renewables_cluster.py b/antarest/study/storage/variantstudy/model/command/remove_renewables_cluster.py index 0e41eef9b5..834dc1043b 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_renewables_cluster.py +++ b/antarest/study/storage/variantstudy/model/command/remove_renewables_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.study.storage.rawstudy.model.filesystem.config.model import Area, FileStudyTreeConfig @@ -15,8 +27,8 @@ class RemoveRenewablesCluster(ICommand): # Overloaded metadata # =================== - command_name = CommandName.REMOVE_RENEWABLES_CLUSTER - version = 1 + command_name: CommandName = CommandName.REMOVE_RENEWABLES_CLUSTER + version: int = 1 # Command parameters # ================== diff --git a/antarest/study/storage/variantstudy/model/command/remove_st_storage.py b/antarest/study/storage/variantstudy/model/command/remove_st_storage.py index 116f402c08..550587535d 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_st_storage.py +++ b/antarest/study/storage/variantstudy/model/command/remove_st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from pydantic import Field @@ -20,14 +32,14 @@ class RemoveSTStorage(ICommand): # Overloaded metadata # =================== - command_name = CommandName.REMOVE_ST_STORAGE - version = 1 + command_name: CommandName = CommandName.REMOVE_ST_STORAGE + version: int = 1 # Command parameters # ================== - area_id: str = Field(description="Area ID", regex=r"[a-z0-9_(),& -]+") - storage_id: str = Field(description="Short term storage ID", regex=r"[a-z0-9_(),& -]+") + area_id: str = Field(description="Area ID", pattern=r"[a-z0-9_(),& -]+") + storage_id: str = Field(description="Short term storage ID", pattern=r"[a-z0-9_(),& -]+") def _apply_config(self, study_data: FileStudyTreeConfig) -> t.Tuple[CommandOutput, t.Dict[str, t.Any]]: """ diff --git a/antarest/study/storage/variantstudy/model/command/replace_matrix.py b/antarest/study/storage/variantstudy/model/command/replace_matrix.py index 6a51ca86b1..8a26f12f28 100644 --- a/antarest/study/storage/variantstudy/model/command/replace_matrix.py +++ b/antarest/study/storage/variantstudy/model/command/replace_matrix.py @@ -1,6 +1,18 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t -from pydantic import validator +from pydantic import Field, ValidationInfo, field_validator from antarest.core.exceptions import ChildNotFoundError from antarest.core.model import JSON @@ -23,16 +35,18 @@ class ReplaceMatrix(ICommand): # Overloaded metadata # =================== - command_name = CommandName.REPLACE_MATRIX - version = 1 + command_name: CommandName = CommandName.REPLACE_MATRIX + version: int = 1 # Command parameters # ================== target: str - matrix: t.Union[t.List[t.List[MatrixData]], str] + matrix: t.Union[t.List[t.List[MatrixData]], str] = Field(validate_default=True) - _validate_matrix = validator("matrix", each_item=True, always=True, allow_reuse=True)(validate_matrix) + @field_validator("matrix", mode="before") + def matrix_validator(cls, matrix: t.Union[t.List[t.List[MatrixData]], str], values: ValidationInfo) -> str: + return validate_matrix(matrix, values.data) def _apply_config(self, study_data: FileStudyTreeConfig) -> t.Tuple[CommandOutput, t.Dict[str, t.Any]]: return ( diff --git a/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py b/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py index ad21a7dd38..a99dfca7a4 100644 --- a/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py +++ b/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py @@ -1,4 +1,15 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from antarest.core.model import JSON @@ -90,7 +101,7 @@ class UpdateBindingConstraint(AbstractBindingConstraintCommand): # Overloaded metadata # =================== - command_name = CommandName.UPDATE_BINDING_CONSTRAINT + command_name: CommandName = CommandName.UPDATE_BINDING_CONSTRAINT version: int = 1 # Command parameters @@ -171,14 +182,14 @@ def _apply(self, study_data: FileStudy) -> CommandOutput: ) study_version = study_data.config.version - props = create_binding_constraint_config(study_version, **self.dict()) - obj = json.loads(props.json(by_alias=True, exclude_unset=True)) + props = create_binding_constraint_config(study_version, **self.model_dump()) + obj = props.model_dump(mode="json", by_alias=True, exclude_unset=True) updated_cfg = binding_constraints[index] updated_cfg.update(obj) - excluded_fields = set(ICommand.__fields__) | {"id"} - updated_properties = self.dict(exclude=excluded_fields, exclude_none=True) + excluded_fields = set(ICommand.model_fields) | {"id"} + updated_properties = self.model_dump(exclude=excluded_fields, exclude_none=True) # This 2nd check is here to remove the last term. if self.coeffs or updated_properties == {"coeffs": {}}: # Remove terms which IDs contain a "%" or a "." in their name @@ -191,8 +202,8 @@ def to_dto(self) -> CommandDTO: matrices = ["values"] + [m.value for m in TermMatrices] matrix_service = self.command_context.matrix_service - excluded_fields = frozenset(ICommand.__fields__) - json_command = json.loads(self.json(exclude=excluded_fields, exclude_none=True)) + excluded_fields = set(ICommand.model_fields) + json_command = self.model_dump(mode="json", exclude=excluded_fields, exclude_none=True) for key in json_command: if key in matrices: json_command[key] = matrix_service.get_matrix_id(json_command[key]) diff --git a/antarest/study/storage/variantstudy/model/command/update_comments.py b/antarest/study/storage/variantstudy/model/command/update_comments.py index 028cbc5060..5a3d57a670 100644 --- a/antarest/study/storage/variantstudy/model/command/update_comments.py +++ b/antarest/study/storage/variantstudy/model/command/update_comments.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict, List, Tuple from antarest.core.model import JSON @@ -16,8 +28,8 @@ class UpdateComments(ICommand): # Overloaded metadata # =================== - command_name = CommandName.UPDATE_COMMENTS - version = 1 + command_name: CommandName = CommandName.UPDATE_COMMENTS + version: int = 1 # Command parameters # ================== diff --git a/antarest/study/storage/variantstudy/model/command/update_config.py b/antarest/study/storage/variantstudy/model/command/update_config.py index b19444f6ae..067b0ecba1 100644 --- a/antarest/study/storage/variantstudy/model/command/update_config.py +++ b/antarest/study/storage/variantstudy/model/command/update_config.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import typing_extensions as te @@ -32,8 +44,8 @@ class UpdateConfig(ICommand): # Overloaded metadata # =================== - command_name = CommandName.UPDATE_CONFIG - version = 1 + command_name: CommandName = CommandName.UPDATE_CONFIG + version: int = 1 # Command parameters # ================== diff --git a/antarest/study/storage/variantstudy/model/command/update_district.py b/antarest/study/storage/variantstudy/model/command/update_district.py index 1a14e37acd..e0d63dfafd 100644 --- a/antarest/study/storage/variantstudy/model/command/update_district.py +++ b/antarest/study/storage/variantstudy/model/command/update_district.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict, List, Optional, Tuple from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig @@ -16,17 +28,17 @@ class UpdateDistrict(ICommand): # Overloaded metadata # =================== - command_name = CommandName.UPDATE_DISTRICT - version = 1 + command_name: CommandName = CommandName.UPDATE_DISTRICT + version: int = 1 # Command parameters # ================== id: str - base_filter: Optional[DistrictBaseFilter] - filter_items: Optional[List[str]] - output: Optional[bool] - comments: Optional[str] + base_filter: Optional[DistrictBaseFilter] = None + filter_items: Optional[List[str]] = None + output: Optional[bool] = None + comments: Optional[str] = None def _apply_config(self, study_data: FileStudyTreeConfig) -> Tuple[CommandOutput, Dict[str, Any]]: base_set = study_data.sets[self.id] diff --git a/antarest/study/storage/variantstudy/model/command/update_playlist.py b/antarest/study/storage/variantstudy/model/command/update_playlist.py index c70dfebbb5..52f6f70c5c 100644 --- a/antarest/study/storage/variantstudy/model/command/update_playlist.py +++ b/antarest/study/storage/variantstudy/model/command/update_playlist.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict, List, Optional, Tuple from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig @@ -16,8 +28,8 @@ class UpdatePlaylist(ICommand): # Overloaded metadata # =================== - command_name = CommandName.UPDATE_PLAYLIST - version = 1 + command_name: CommandName = CommandName.UPDATE_PLAYLIST + version: int = 1 # Command parameters # ================== diff --git a/antarest/study/storage/variantstudy/model/command/update_raw_file.py b/antarest/study/storage/variantstudy/model/command/update_raw_file.py index 3e7b3b8759..1a3414f90b 100644 --- a/antarest/study/storage/variantstudy/model/command/update_raw_file.py +++ b/antarest/study/storage/variantstudy/model/command/update_raw_file.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import base64 from typing import Any, Dict, List, Tuple @@ -17,8 +29,8 @@ class UpdateRawFile(ICommand): # Overloaded metadata # =================== - command_name = CommandName.UPDATE_FILE - version = 1 + command_name: CommandName = CommandName.UPDATE_FILE + version: int = 1 # Command parameters # ================== diff --git a/antarest/study/storage/variantstudy/model/command/update_scenario_builder.py b/antarest/study/storage/variantstudy/model/command/update_scenario_builder.py index ff8e1311ac..86a127f776 100644 --- a/antarest/study/storage/variantstudy/model/command/update_scenario_builder.py +++ b/antarest/study/storage/variantstudy/model/command/update_scenario_builder.py @@ -1,8 +1,20 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import numpy as np -from requests.structures import CaseInsensitiveDict +from antarest.core.requests import CaseInsensitiveDict from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.variantstudy.model.command.common import CommandName, CommandOutput @@ -33,13 +45,13 @@ class UpdateScenarioBuilder(ICommand): # Overloaded metadata # =================== - command_name = CommandName.UPDATE_SCENARIO_BUILDER - version = 1 + command_name: CommandName = CommandName.UPDATE_SCENARIO_BUILDER + version: int = 1 # Command parameters # ================== - data: t.Dict[str, t.Any] + data: t.Union[t.Dict[str, t.Any], t.Mapping[str, t.Any], t.MutableMapping[str, t.Any]] def _apply(self, study_data: FileStudy) -> CommandOutput: """ diff --git a/antarest/study/storage/variantstudy/model/command_context.py b/antarest/study/storage/variantstudy/model/command_context.py index a361d40959..5996e63528 100644 --- a/antarest/study/storage/variantstudy/model/command_context.py +++ b/antarest/study/storage/variantstudy/model/command_context.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pydantic import BaseModel from antarest.matrixstore.service import ISimpleMatrixService @@ -12,4 +24,3 @@ class CommandContext(BaseModel): class Config: arbitrary_types_allowed = True - copy_on_model_validation = False diff --git a/antarest/study/storage/variantstudy/model/dbmodel.py b/antarest/study/storage/variantstudy/model/dbmodel.py index d9a7e5fc55..421caf87d7 100644 --- a/antarest/study/storage/variantstudy/model/dbmodel.py +++ b/antarest/study/storage/variantstudy/model/dbmodel.py @@ -1,5 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime -import json import typing as t import uuid from pathlib import Path @@ -8,6 +19,7 @@ from sqlalchemy.orm import relationship # type: ignore from antarest.core.persistence import Base +from antarest.core.serialization import from_json from antarest.study.model import Study from antarest.study.storage.variantstudy.model.model import CommandDTO @@ -57,7 +69,7 @@ class CommandBlock(Base): # type: ignore def to_dto(self) -> CommandDTO: # Database may lack a version number, defaulting to 1 if so. version = self.version or 1 - return CommandDTO(id=self.id, action=self.command, args=json.loads(self.args), version=version) + return CommandDTO(id=self.id, action=self.command, args=from_json(self.args), version=version) def __str__(self) -> str: return ( diff --git a/antarest/study/storage/variantstudy/model/interfaces.py b/antarest/study/storage/variantstudy/model/interfaces.py index 31b14fabd7..cfe392a024 100644 --- a/antarest/study/storage/variantstudy/model/interfaces.py +++ b/antarest/study/storage/variantstudy/model/interfaces.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import abc from abc import abstractmethod from typing import List, Optional, Tuple diff --git a/antarest/study/storage/variantstudy/model/model.py b/antarest/study/storage/variantstudy/model/model.py index e170bf4383..0be3c75353 100644 --- a/antarest/study/storage/variantstudy/model/model.py +++ b/antarest/study/storage/variantstudy/model/model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import uuid @@ -57,7 +69,7 @@ class CommandDTO(BaseModel): version: The version of the command. """ - id: t.Optional[str] + id: t.Optional[str] = None action: str args: t.Union[t.MutableSequence[JSON], JSON] version: int = 1 diff --git a/antarest/study/storage/variantstudy/repository.py b/antarest/study/storage/variantstudy/repository.py index 3f5ca51fdf..fc4fcc3809 100644 --- a/antarest/study/storage/variantstudy/repository.py +++ b/antarest/study/storage/variantstudy/repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from sqlalchemy.orm import Session, joinedload # type: ignore diff --git a/antarest/study/storage/variantstudy/snapshot_generator.py b/antarest/study/storage/variantstudy/snapshot_generator.py index ee4532349f..086c6d3952 100644 --- a/antarest/study/storage/variantstudy/snapshot_generator.py +++ b/antarest/study/storage/variantstudy/snapshot_generator.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ This module dedicated to variant snapshot generation. """ @@ -121,7 +133,7 @@ def generate_snapshot( else: try: - notifier(results.json()) + notifier(results.model_dump_json()) except Exception as exc: # This exception is ignored, because it is not critical. logger.warning(f"Error while sending notification: {exc}", exc_info=True) @@ -191,7 +203,7 @@ def _read_additional_data(self, file_study: FileStudy) -> StudyAdditionalData: horizon = file_study.tree.get(url=["settings", "generaldata", "general", "horizon"]) author = file_study.tree.get(url=["study", "antares", "author"]) patch = self.patch_service.get_from_filestudy(file_study) - study_additional_data = StudyAdditionalData(horizon=horizon, author=author, patch=patch.json()) + study_additional_data = StudyAdditionalData(horizon=horizon, author=author, patch=patch.model_dump_json()) return study_additional_data def _update_cache(self, file_study: FileStudy) -> None: @@ -199,7 +211,7 @@ def _update_cache(self, file_study: FileStudy) -> None: self.cache.invalidate(f"{CacheConstants.RAW_STUDY}/{file_study.config.study_id}") self.cache.put( f"{CacheConstants.STUDY_FACTORY}/{file_study.config.study_id}", - FileStudyTreeConfigDTO.from_build_config(file_study.config).dict(), + FileStudyTreeConfigDTO.from_build_config(file_study.config).model_dump(), ) diff --git a/antarest/study/storage/variantstudy/variant_command_extractor.py b/antarest/study/storage/variantstudy/variant_command_extractor.py index bd052a6c0a..76df6653c4 100644 --- a/antarest/study/storage/variantstudy/variant_command_extractor.py +++ b/antarest/study/storage/variantstudy/variant_command_extractor.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from typing import List, Tuple diff --git a/antarest/study/storage/variantstudy/variant_command_generator.py b/antarest/study/storage/variantstudy/variant_command_generator.py index 7e56f370ec..de4bd60c0f 100644 --- a/antarest/study/storage/variantstudy/variant_command_generator.py +++ b/antarest/study/storage/variantstudy/variant_command_generator.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import shutil import uuid diff --git a/antarest/study/storage/variantstudy/variant_study_service.py b/antarest/study/storage/variantstudy/variant_study_service.py index a0c03a8457..8737824696 100644 --- a/antarest/study/storage/variantstudy/variant_study_service.py +++ b/antarest/study/storage/variantstudy/variant_study_service.py @@ -1,10 +1,21 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import concurrent.futures -import json import logging import re import shutil import typing as t -from datetime import datetime +from datetime import datetime, timedelta from functools import reduce from pathlib import Path from uuid import uuid4 @@ -31,11 +42,14 @@ from antarest.core.jwt import DEFAULT_ADMIN_USER from antarest.core.model import JSON, PermissionInfo, PublicMode, StudyPermissionType from antarest.core.requests import RequestParameters, UserHasNotPermissionError +from antarest.core.serialization import to_json_string from antarest.core.tasks.model import CustomTaskEventMessages, TaskDTO, TaskResult, TaskType from antarest.core.tasks.service import DEFAULT_AWAIT_MAX_TIMEOUT, ITaskService, TaskUpdateNotifier, noop_notifier +from antarest.core.utils.fastapi_sqlalchemy import db from antarest.core.utils.utils import assert_this, suppress_exception from antarest.matrixstore.service import MatrixService from antarest.study.model import RawStudy, Study, StudyAdditionalData, StudyMetadataDTO, StudySimResultDTO +from antarest.study.repository import AccessPermissions, StudyFilter from antarest.study.storage.abstract_storage_service import AbstractStorageService from antarest.study.storage.patch_service import PatchService from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig, FileStudyTreeConfigDTO @@ -176,7 +190,10 @@ def append_commands( # noinspection PyArgumentList new_commands = [ CommandBlock( - command=command.action, args=json.dumps(command.args), index=(first_index + i), version=command.version + command=command.action, + args=to_json_string(command.args), + index=(first_index + i), + version=command.version, ) for i, command in enumerate(validated_commands) ] @@ -211,7 +228,7 @@ def replace_commands( validated_commands = transform_command_to_dto(command_objs, commands) # noinspection PyArgumentList study.commands = [ - CommandBlock(command=command.action, args=json.dumps(command.args), index=i, version=command.version) + CommandBlock(command=command.action, args=to_json_string(command.args), index=i, version=command.version) for i, command in enumerate(validated_commands) ] self.invalidate_cache(study, invalidate_self_snapshot=True) @@ -302,7 +319,7 @@ def update_command( index = [command.id for command in study.commands].index(command_id) if index >= 0: study.commands[index].command = validated_commands[0].action - study.commands[index].args = json.dumps(validated_commands[0].args) + study.commands[index].args = to_json_string(validated_commands[0].args) self.invalidate_cache(study, invalidate_self_snapshot=True) def export_commands_matrices(self, study_id: str, params: RequestParameters) -> FileDownloadTaskDTO: @@ -482,7 +499,7 @@ def get( Returns: study data formatted in json """ - self._safe_generation(metadata, timeout=60) + self._safe_generation(metadata, timeout=600) self.repository.refresh(metadata) return super().get( metadata=metadata, @@ -610,10 +627,10 @@ def callback(notifier: TaskUpdateNotifier) -> TaskResult: ) return TaskResult( success=generate_result.success, - message=f"{study_id} generated successfully" - if generate_result.success - else f"{study_id} not generated", - return_value=generate_result.json(), + message=( + f"{study_id} generated successfully" if generate_result.success else f"{study_id} not generated" + ), + return_value=generate_result.model_dump_json(), ) metadata.generation_task = self.task_service.add_task( @@ -704,7 +721,7 @@ def notify(command_index: int, command_result: bool, command_message: str) -> No success=command_result, message=command_message, ) - notifier(command_result_obj.json()) + notifier(command_result_obj.model_dump_json()) self.event_bus.push( Event( type=EventType.STUDY_VARIANT_GENERATION_COMMAND_RESULT, @@ -924,7 +941,7 @@ def get_study_sim_result(self, study: VariantStudy) -> t.List[StudySimResultDTO] study: study Returns: study output data """ - self._safe_generation(study, timeout=60) + self._safe_generation(study, timeout=600) return super().get_study_sim_result(study=study) def set_reference_output(self, metadata: VariantStudy, output_id: str, status: bool) -> None: @@ -1038,3 +1055,67 @@ def initialize_additional_data(self, variant_study: VariantStudy) -> bool: exc_info=e, ) return False + + def clear_all_snapshots(self, retention_hours: timedelta, params: t.Optional[RequestParameters] = None) -> str: + """ + Admin command that clear all variant snapshots older than `retention_hours` (in hours). + Only available for admin users. + + Args: + retention_hours: number of retention hours + params: request parameters used to identify the user status + Returns: None + + Raises: + UserHasNotPermissionError + """ + if params is None or (params.user and not params.user.is_site_admin() and not params.user.is_admin_token()): + raise UserHasNotPermissionError() + + task_name = f"Cleaning all snapshot updated or accessed at least {retention_hours} hours ago." + + snapshot_clearing_task_instance = SnapshotCleanerTask( + variant_study_service=self, retention_hours=retention_hours + ) + + return self.task_service.add_task( + snapshot_clearing_task_instance, + task_name, + task_type=TaskType.SNAPSHOT_CLEARING, + ref_id="SNAPSHOT_CLEANING", + custom_event_messages=None, + request_params=params, + ) + + +class SnapshotCleanerTask: + def __init__( + self, + variant_study_service: VariantStudyService, + retention_hours: timedelta, + ) -> None: + self._variant_study_service = variant_study_service + self._retention_hours = retention_hours + + def _clear_all_snapshots(self) -> None: + with db(): + variant_list = self._variant_study_service.repository.get_all( + study_filter=StudyFilter( + variant=True, + access_permissions=AccessPermissions(is_admin=True), + ) + ) + for variant in variant_list: + if variant.updated_at and variant.updated_at < datetime.utcnow() - self._retention_hours: + if variant.last_access and variant.last_access < datetime.utcnow() - self._retention_hours: + self._variant_study_service.clear_snapshot(variant) + + def run_task(self, notifier: TaskUpdateNotifier) -> TaskResult: + msg = f"Start cleaning all snapshots updated or accessed {self._retention_hours} hours ago." + notifier(msg) + self._clear_all_snapshots() + msg = f"All selected snapshots were successfully cleared." + notifier(msg) + return TaskResult(success=True, message=msg) + + __call__ = run_task diff --git a/antarest/study/web/__init__.py b/antarest/study/web/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/study/web/__init__.py +++ b/antarest/study/web/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/study/web/raw_studies_blueprint.py b/antarest/study/web/raw_studies_blueprint.py index 425c67e6b5..e3b114d6d5 100644 --- a/antarest/study/web/raw_studies_blueprint.py +++ b/antarest/study/web/raw_studies_blueprint.py @@ -1,7 +1,18 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import collections import http import io -import json import logging import typing as t from pathlib import Path, PurePosixPath @@ -14,6 +25,7 @@ from antarest.core.jwt import JWTUser from antarest.core.model import SUB_JSON from antarest.core.requests import RequestParameters +from antarest.core.serialization import from_json, to_json from antarest.core.swagger import get_path_examples from antarest.core.utils.utils import sanitize_string, sanitize_uuid from antarest.core.utils.web import APITag @@ -136,7 +148,7 @@ def get_study( # Use `JSONResponse` to ensure to return a valid JSON response # that checks `NaN` and `Infinity` values. try: - output = json.loads(output) + output = from_json(output) return JSONResponse(content=output) except ValueError as exc: raise HTTPException( @@ -170,15 +182,24 @@ def get_study( # even though they are not standard JSON values because they are supported in JavaScript. # Additionally, we cannot use `orjson` because, despite its superior performance, it converts # `NaN` and other values to `null`, even when using a custom encoder. - json_response = json.dumps( - output, - ensure_ascii=False, - allow_nan=True, - indent=None, - separators=(",", ":"), - ).encode("utf-8") + json_response = to_json(output) return Response(content=json_response, media_type="application/json") + @bp.delete( + "/studies/{uuid}/raw", + tags=[APITag.study_raw_data], + summary="Delete files or folders located inside the 'User' folder", + response_model=None, + ) + def delete_file( + uuid: str, + path: str = Param("/", examples=["user/wind_solar/synthesis_windSolar.xlsx"]), # type: ignore + current_user: JWTUser = Depends(auth.get_current_user), + ) -> t.Any: + uuid = sanitize_uuid(uuid) + logger.info(f"Deleting path {path} inside study {uuid}", extra={"user": current_user.id}) + study_service.delete_file_or_folder(uuid, path, current_user) + @bp.get( "/studies/{uuid}/areas/aggregate/mc-ind/{output_id}", tags=[APITag.study_raw_data], @@ -242,7 +263,7 @@ def aggregate_areas_raw_data( df_matrix, study_service.file_transfer_manager, export_format, - True, + False, True, download_name, download_log, @@ -311,7 +332,7 @@ def aggregate_links_raw_data( df_matrix, study_service.file_transfer_manager, export_format, - True, + False, True, download_name, download_log, @@ -378,7 +399,7 @@ def aggregate_areas_raw_data__all( df_matrix, study_service.file_transfer_manager, export_format, - True, + False, True, download_name, download_log, @@ -444,7 +465,7 @@ def aggregate_links_raw_data__all( df_matrix, study_service.file_transfer_manager, export_format, - True, + False, True, download_name, download_log, diff --git a/antarest/study/web/studies_blueprint.py b/antarest/study/web/studies_blueprint.py index 1dbc4810f7..41398dee6a 100644 --- a/antarest/study/web/studies_blueprint.py +++ b/antarest/study/web/studies_blueprint.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import collections import io import logging @@ -86,7 +98,7 @@ def get_studies( exists: t.Optional[bool] = Query(None, description="Filter studies based on their existence on disk."), workspace: str = Query("", description="Filter studies based on their workspace."), folder: str = Query("", description="Filter studies based on their folder."), - sort_by: t.Optional[StudySortBy] = Query( + sort_by: StudySortBy = Query( None, description="Sort studies based on their name (case-insensitive) or creation date.", alias="sortBy", @@ -715,7 +727,7 @@ def output_download( extra={"user": current_user.id}, ) params = RequestParameters(user=current_user) - accept = request.headers.get("Accept") + accept = request.headers["Accept"] filetype = ExportFormat.from_dto(accept) content = study_service.download_outputs( diff --git a/antarest/study/web/study_data_blueprint.py b/antarest/study/web/study_data_blueprint.py index 8a960da5f3..2128ed849c 100644 --- a/antarest/study/web/study_data_blueprint.py +++ b/antarest/study/web/study_data_blueprint.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import enum import logging import typing as t @@ -17,7 +29,7 @@ from antarest.matrixstore.matrix_editor import MatrixEditInstruction from antarest.study.business.adequacy_patch_management import AdequacyPatchFormFields from antarest.study.business.advanced_parameters_management import AdvancedParamsFormFields -from antarest.study.business.allocation_management import AllocationFormFields, AllocationMatrix +from antarest.study.business.allocation_management import AllocationField, AllocationFormFields, AllocationMatrix from antarest.study.business.area_management import AreaCreationDTO, AreaInfoDTO, AreaType, LayerInfoDTO, UpdateAreaUi from antarest.study.business.areas.hydro_management import InflowStructure, ManagementOptionsFormFields from antarest.study.business.areas.properties_management import PropertiesFormFields @@ -48,7 +60,12 @@ ConstraintOutput, ConstraintTerm, ) -from antarest.study.business.correlation_management import CorrelationFormFields, CorrelationManager, CorrelationMatrix +from antarest.study.business.correlation_management import ( + AreaCoefficientItem, + CorrelationFormFields, + CorrelationManager, + CorrelationMatrix, +) from antarest.study.business.district_manager import DistrictCreationDTO, DistrictInfoDTO, DistrictUpdateDTO from antarest.study.business.general_management import GeneralFormFields from antarest.study.business.link_management import LinkInfoDTO @@ -110,11 +127,11 @@ def create_study_data_routes(study_service: StudyService, config: Config) -> API "/studies/{uuid}/areas", tags=[APITag.study_data], summary="Get all areas basic info", - response_model=t.Union[t.List[AreaInfoDTO], t.Dict[str, t.Any]], # type: ignore + response_model=t.Union[t.List[AreaInfoDTO], t.Dict[str, t.Any]], ) def get_areas( uuid: str, - type: t.Optional[AreaType] = None, + type: AreaType = Query(None), ui: bool = False, current_user: JWTUser = Depends(auth.get_current_user), ) -> t.Union[t.List[AreaInfoDTO], t.Dict[str, t.Any]]: @@ -491,7 +508,6 @@ def get_inflow_structure( "/studies/{uuid}/areas/{area_id}/hydro/inflow-structure", tags=[APITag.study_data], summary="Update inflow structure values", - response_model=InflowStructure, ) def update_inflow_structure( uuid: str, @@ -506,7 +522,7 @@ def update_inflow_structure( ) params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - return study_service.hydro_manager.update_inflow_structure(study, area_id, values) + study_service.hydro_manager.update_inflow_structure(study, area_id, values) @bp.put( "/studies/{uuid}/matrix", @@ -613,12 +629,12 @@ def set_playlist( "/studies/{uuid}/config/playlist", tags=[APITag.study_data], summary="Get playlist config", - response_model=t.Dict[int, float], + response_model=t.Optional[t.Dict[int, float]], ) def get_playlist_config( uuid: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> t.Any: + ) -> t.Optional[t.Dict[int, float]]: logger.info( f"Fetching playlist config for study {uuid}", extra={"user": current_user.id}, @@ -1079,10 +1095,10 @@ def update_version( def get_binding_constraint_list( uuid: str, enabled: t.Optional[bool] = Query(None, description="Filter results based on enabled status"), - operator: t.Optional[BindingConstraintOperator] = Query(None, description="Filter results based on operator"), + operator: BindingConstraintOperator = Query(None, description="Filter results based on operator"), comments: str = Query("", description="Filter results based on comments (word match)"), group: str = Query("", description="filter binding constraints based on group name (exact match)"), - time_step: t.Optional[BindingConstraintFrequency] = Query( + time_step: BindingConstraintFrequency = Query( None, description="Filter results based on time step", alias="timeStep", @@ -1132,7 +1148,7 @@ def get_binding_constraint_list( "/studies/{uuid}/bindingconstraints/{binding_constraint_id}", tags=[APITag.study_data], summary="Get binding constraint", - response_model=ConstraintOutput, # type: ignore + response_model=ConstraintOutput, # TODO: redundant ? ) def get_binding_constraint( uuid: str, @@ -1520,8 +1536,8 @@ def set_allocation_form_fields( ..., example=AllocationFormFields( allocation=[ - {"areaId": "EAST", "coefficient": 1}, - {"areaId": "NORTH", "coefficient": 0.20}, + AllocationField.model_validate({"areaId": "EAST", "coefficient": 1}), + AllocationField.model_validate({"areaId": "NORTH", "coefficient": 0.20}), ] ), ), @@ -1553,8 +1569,8 @@ def set_allocation_form_fields( def get_correlation_matrix( uuid: str, columns: t.Optional[str] = Query( - None, - examples={ + default=None, + openapi_examples={ "all areas": { "description": "get the correlation matrix for all areas (by default)", "value": "", @@ -1686,8 +1702,8 @@ def set_correlation_form_fields( ..., example=CorrelationFormFields( correlation=[ - {"areaId": "east", "coefficient": 80}, - {"areaId": "north", "coefficient": 20}, + AreaCoefficientItem.model_validate({"areaId": "east", "coefficient": 80}), + AreaCoefficientItem.model_validate({"areaId": "north", "coefficient": 20}), ] ), ), diff --git a/antarest/study/web/variant_blueprint.py b/antarest/study/web/variant_blueprint.py index 060ff167e9..bc000fadf4 100644 --- a/antarest/study/web/variant_blueprint.py +++ b/antarest/study/web/variant_blueprint.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. +import datetime import logging from typing import List, Optional, Union @@ -95,12 +107,7 @@ def create_variant( "/studies/{uuid}/variants", tags=[APITag.study_variant_management], summary="Get children variants", - responses={ - 200: { - "description": "The list of children study variant", - "model": List[StudyMetadataDTO], - } - }, + response_model=None, # To cope with recursive models issues ) def get_variants( uuid: str, @@ -409,4 +416,33 @@ def create_from_variant( params = RequestParameters(user=current_user) raise NotImplementedError() + @bp.put( + "/studies/variants/clear-snapshots", + tags=[APITag.study_variant_management], + summary="Clear variant snapshots", + responses={ + 200: { + "description": "Delete snapshots older than a specific number of hours. By default, this number is 24." + } + }, + ) + def clear_variant_snapshots( + hours: int = 24, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> str: + """ + Endpoint that clear `limit` hours old and older variant snapshots. + + Args: limit (int, optional): Number of hours to clear. Defaults to 24. + + Returns: ID of the task running the snapshot clearing. + """ + retention_hours = datetime.timedelta(hours=hours) + logger.info( + f"Delete all variant snapshots older than {retention_hours} hours.", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + return variant_study_service.clear_all_snapshots(retention_hours, params) + return bp diff --git a/antarest/study/web/watcher_blueprint.py b/antarest/study/web/watcher_blueprint.py index f5c8c6b922..a98ccfe0c5 100644 --- a/antarest/study/web/watcher_blueprint.py +++ b/antarest/study/web/watcher_blueprint.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from http import HTTPStatus from http.client import HTTPException diff --git a/antarest/study/web/xpansion_studies_blueprint.py b/antarest/study/web/xpansion_studies_blueprint.py index 1b46af1a84..5372fb0cea 100644 --- a/antarest/study/web/xpansion_studies_blueprint.py +++ b/antarest/study/web/xpansion_studies_blueprint.py @@ -1,4 +1,15 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import typing as t @@ -9,6 +20,7 @@ from antarest.core.jwt import JWTUser from antarest.core.model import JSON, StudyPermissionType from antarest.core.requests import RequestParameters +from antarest.core.serialization import to_json from antarest.core.utils.web import APITag from antarest.login.auth import Auth from antarest.study.business.xpansion_management import ( @@ -127,7 +139,7 @@ def add_candidate( current_user: JWTUser = Depends(auth.get_current_user), ) -> XpansionCandidateDTO: logger.info( - f"Adding new candidate {xpansion_candidate_dto.dict(by_alias=True)} to study {uuid}", + f"Adding new candidate {xpansion_candidate_dto.model_dump(by_alias=True)} to study {uuid}", extra={"user": current_user.id}, ) params = RequestParameters(user=current_user) @@ -270,13 +282,7 @@ def get_resource_content( except (AttributeError, UnicodeDecodeError): pass - json_response = json.dumps( - output, - ensure_ascii=False, - allow_nan=True, - indent=None, - separators=(",", ":"), - ).encode("utf-8") + json_response = to_json(output) return Response(content=json_response, media_type="application/json") @bp.get( @@ -286,7 +292,7 @@ def get_resource_content( ) def list_resources( uuid: str, - resource_type: t.Optional[XpansionResourceFileType] = None, + resource_type: XpansionResourceFileType, current_user: JWTUser = Depends(auth.get_current_user), ) -> t.Any: logger.info( @@ -298,8 +304,6 @@ def list_resources( StudyPermissionType.READ, RequestParameters(user=current_user), ) - if resource_type is None: - return study_service.xpansion_manager.list_root_files(study) return study_service.xpansion_manager.list_resources(study, resource_type) return bp diff --git a/antarest/tools/__init__.py b/antarest/tools/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/tools/__init__.py +++ b/antarest/tools/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/tools/admin.py b/antarest/tools/admin.py index 2b89ffb013..39f15991cd 100644 --- a/antarest/tools/admin.py +++ b/antarest/tools/admin.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from pathlib import Path diff --git a/antarest/tools/admin_lib.py b/antarest/tools/admin_lib.py index 5f64dd3c6f..4a27593b96 100644 --- a/antarest/tools/admin_lib.py +++ b/antarest/tools/admin_lib.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from pathlib import Path diff --git a/antarest/tools/cli.py b/antarest/tools/cli.py index 9a591b0d9e..85eef22128 100644 --- a/antarest/tools/cli.py +++ b/antarest/tools/cli.py @@ -1,12 +1,25 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from pathlib import Path from typing import Optional import click +from httpx import Client from antarest.study.model import NEW_DEFAULT_STUDY_VERSION from antarest.study.storage.study_upgrader import StudyUpgrader -from antarest.tools.lib import extract_commands, generate_diff, generate_study +from antarest.tools.lib import create_http_client, extract_commands, generate_diff, generate_study @click.group(context_settings={"max_content_width": 120}) @@ -31,6 +44,12 @@ def commands() -> None: type=str, help="Authentication token if server needs one", ) +@click.option( + "--no-verify", + is_flag=True, + default=False, + help="Disables SSL certificate verification", +) @click.option( "--output", "-o", @@ -70,6 +89,7 @@ def cli_apply_script( output: Optional[str], host: Optional[str], auth_token: Optional[str], + no_verify: bool, version: str, ) -> None: """Apply a variant script onto an AntaresWeb study variant""" @@ -83,7 +103,10 @@ def cli_apply_script( print("--study_id must be set") exit(1) - res = generate_study(Path(input), study_id, output, host, auth_token, version) + client = None + if host: + client = create_http_client(verify=not no_verify, auth_token=auth_token) + res = generate_study(Path(input), study_id, output, host, client, version) print(res) diff --git a/antarest/tools/lib.py b/antarest/tools/lib.py index 60e3215f5b..5f3aafc74a 100644 --- a/antarest/tools/lib.py +++ b/antarest/tools/lib.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import logging import os @@ -8,20 +20,11 @@ from zipfile import ZipFile import numpy as np - -try: - # The HTTPX equivalent of `requests.Session` is `httpx.Client`. - import httpx as requests - from httpx import Client as Session -except ImportError: - # noinspection PyUnresolvedReferences, PyPackageRequirements - import requests - - # noinspection PyUnresolvedReferences,PyPackageRequirements - from requests import Session +from httpx import Client from antarest.core.cache.business.local_chache import LocalCache from antarest.core.config import CacheConfig +from antarest.core.serialization import from_json, to_json_string from antarest.core.tasks.model import TaskDTO from antarest.core.utils.utils import StopWatch, get_local_path from antarest.matrixstore.repository import MatrixContentRepository @@ -49,34 +52,28 @@ def apply_commands(self, commands: List[CommandDTO], matrices_dir: Path) -> Gene raise NotImplementedError() +def set_auth_token(client: Client, auth_token: Optional[str] = None) -> Client: + if auth_token is not None: + client.headers.update({"Authorization": f"Bearer {auth_token}"}) + return client + + +def create_http_client(verify: bool, auth_token: Optional[str] = None) -> Client: + client = Client(verify=verify) + set_auth_token(client, auth_token) + return client + + class RemoteVariantGenerator(IVariantGenerator): def __init__( self, study_id: str, - host: Optional[str] = None, - token: Optional[str] = None, - session: Optional[Session] = None, + host: str, + session: Client, ): self.study_id = study_id - - # todo: find the correct way to handle certificates. - # By default, Requests/Httpx verifies SSL certificates for HTTPS requests. - # When verify is set to `False`, requests will accept any TLS certificate presented - # by the server,and will ignore hostname mismatches and/or expired certificates, - # which will make your application vulnerable to man-in-the-middle (MitM) attacks. - # Setting verify to False may be useful during local development or testing. - if Session.__name__ == "Client": - # noinspection PyArgumentList - self.session = session or Session(verify=False) - else: - self.session = session or Session() - self.session.verify = False - + self.session = session self.host = host - if session is None and host is None: - raise ValueError("Missing either session or host") - if token is not None: - self.session.headers.update({"Authorization": f"Bearer {token}"}) def apply_commands( self, @@ -102,7 +99,7 @@ def apply_commands( res = self.session.post( self.build_url(f"/v1/studies/{self.study_id}/commands"), - json=[command.dict() for command in commands], + json=[command.model_dump() for command in commands], ) res.raise_for_status() stopwatch.log_elapsed(lambda x: logger.info(f"Command upload done in {x}s")) @@ -121,7 +118,7 @@ def apply_commands( # This should not happen, but if it does, we return a failed result return GenerationResultInfoDTO(success=False, details=[]) - info = json.loads(task_result.result.return_value) + info = from_json(task_result.result.return_value) return GenerationResultInfoDTO(**info) def build_url(self, url: str) -> str: @@ -211,10 +208,7 @@ def extract_commands(study_path: Path, commands_output_dir: Path) -> None: command_list = extractor.extract(study) (commands_output_dir / COMMAND_FILE).write_text( - json.dumps( - [command.dict(exclude={"id"}) for command in command_list], - indent=2, - ) + to_json_string([command.model_dump(exclude={"id"}) for command in command_list], indent=2) ) @@ -303,10 +297,7 @@ def generate_diff( ) (output_dir / COMMAND_FILE).write_text( - json.dumps( - [command.to_dto().dict(exclude={"id"}) for command in diff_commands], - indent=2, - ) + to_json_string([command.to_dto().model_dump(exclude={"id"}) for command in diff_commands], indent=2) ) needed_matrices: Set[str] = set() @@ -336,7 +327,7 @@ def generate_study( study_id: Optional[str], output: Optional[str] = None, host: Optional[str] = None, - token: Optional[str] = None, + session: Optional[Client] = None, study_version: str = NEW_DEFAULT_STUDY_VERSION, ) -> GenerationResultInfoDTO: """ @@ -350,7 +341,7 @@ def generate_study( If `study_id` and `host` are not provided, this must be specified. host: The URL of the Antares server to use for generating the new study. If `study_id` is not provided, this is ignored. - token: The authentication token to use when connecting to the Antares server. + session: The session to use when connecting to the Antares server. If `host` is not provided, this is ignored. study_version: The target version of the generated study. @@ -358,8 +349,9 @@ def generate_study( GenerationResultInfoDTO: A data transfer object containing information about the generation result. """ generator: Union[RemoteVariantGenerator, LocalVariantGenerator] - if study_id is not None and host is not None: - generator = RemoteVariantGenerator(study_id, host, token) + + if study_id is not None and host is not None and session is not None: + generator = RemoteVariantGenerator(study_id, host, session) elif output is None: raise TypeError("'output' must be set") else: diff --git a/antarest/worker/__init__.py b/antarest/worker/__init__.py index e69de29bb2..058c6b221a 100644 --- a/antarest/worker/__init__.py +++ b/antarest/worker/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/antarest/worker/archive_worker.py b/antarest/worker/archive_worker.py index 0ef7bedc31..4fbc6a0631 100644 --- a/antarest/worker/archive_worker.py +++ b/antarest/worker/archive_worker.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging from pathlib import Path @@ -46,10 +58,10 @@ def __init__( ) def _execute_task(self, task_info: WorkerTaskCommand) -> TaskResult: - logger.info(f"Executing task {task_info.json()}") + logger.info(f"Executing task {task_info.model_dump_json()}") try: # sourcery skip: extract-method - archive_args = ArchiveTaskArgs.parse_obj(task_info.task_args) + archive_args = ArchiveTaskArgs.model_validate(task_info.task_args) dest = self.translate_path(Path(archive_args.dest)) src = self.translate_path(Path(archive_args.src)) stopwatch = StopWatch() @@ -63,7 +75,7 @@ def _execute_task(self, task_info: WorkerTaskCommand) -> TaskResult: return TaskResult(success=True, message="") except Exception as e: logger.warning( - f"Task {task_info.json()} failed", + f"Task {task_info.model_dump_json()} failed", exc_info=e, ) return TaskResult(success=False, message=str(e)) diff --git a/antarest/worker/archive_worker_service.py b/antarest/worker/archive_worker_service.py index 73106f1fc2..b8e505fa8c 100644 --- a/antarest/worker/archive_worker_service.py +++ b/antarest/worker/archive_worker_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import argparse import logging from pathlib import Path @@ -7,7 +19,7 @@ from antarest.core.config import Config from antarest.core.logging.utils import configure_logger from antarest.core.utils.utils import get_local_path -from antarest.utils import create_archive_worker +from antarest.service_creator import create_archive_worker # use the real module name instead of `__name__` (because `__name__ == "__main__"`) logger = logging.getLogger("antarest.worker.archive_worker_service") diff --git a/antarest/worker/simulator_worker.py b/antarest/worker/simulator_worker.py index d37a8825f5..583f340e7a 100644 --- a/antarest/worker/simulator_worker.py +++ b/antarest/worker/simulator_worker.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import logging import subprocess @@ -69,7 +81,7 @@ def execute_kirshoff_constraint_generation_task(self, task_info: WorkerTaskComma def execute_timeseries_generation_task(self, task_info: WorkerTaskCommand) -> TaskResult: result = TaskResult(success=True, message="", return_value="") - task = GenerateTimeseriesTaskArgs.parse_obj(task_info.task_args) + task = GenerateTimeseriesTaskArgs.model_validate(task_info.task_args) binary = ( self.binaries[task.study_version] if task.study_version in self.binaries diff --git a/antarest/worker/worker.py b/antarest/worker/worker.py index d292d7a8b8..7dc2534764 100644 --- a/antarest/worker/worker.py +++ b/antarest/worker/worker.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import time from abc import abstractmethod @@ -100,8 +112,8 @@ def _loop(self) -> None: time.sleep(1) async def _listen_for_tasks(self, event: Event) -> None: - logger.info(f"Accepting new task {event.json()}") - task_info = WorkerTaskCommand.parse_obj(event.payload) + logger.info(f"Accepting new task {event.model_dump_json()}") + task_info = WorkerTaskCommand.model_validate(event.payload) self.event_bus.push( Event( type=EventType.WORKER_TASK_STARTED, @@ -119,7 +131,7 @@ def _safe_execute_task(self, task_info: WorkerTaskCommand) -> TaskResult: return self._execute_task(task_info) except Exception as e: logger.error( - f"Unexpected error occurred when executing task {task_info.json()}", + f"Unexpected error occurred when executing task {task_info.model_dump_json()}", exc_info=e, ) return TaskResult(success=False, message=repr(e)) diff --git a/antarest/wsgi.py b/antarest/wsgi.py index a46965cf93..b39d3a1153 100644 --- a/antarest/wsgi.py +++ b/antarest/wsgi.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os from pathlib import Path diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e384f281d9..9b9c729cf5 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,54 @@ Antares Web Changelog ===================== +v2.17.6 (2024-09-25) +-------------------- + +## What's Changed + +### Features + +* **upgrader**: use `antares-study-version` package [`2108`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2108) +* **ts-gen**: add timeseries generation [`2112`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2112) +* **bc**: show existing matrices only [`2109`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2109) +* **aggregation-api**: add new endpoint for `economy/mc-all` aggregation [`2092`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2092) +* **installer**: add installer as a submodule [`2110`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2110) +* **ui-debug**: update the view [`2093`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2093) + +### Bug Fixes + +* **ui-areas**: add correct unit in title in Properties form [`2115`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2115) +* **hydro**: wrong frequency for inflow pattern [`2116`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2116) +* **adequacy-patch**: csr relaxation must be an integer [`2123`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2123) +* **launcher-api**: remove orphan JobResults visibility permissions [`2128`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2128) +* **ui**: add missing `i18n` key and styles on `EmptyView` [`2127`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2127) + +### Continuous integration + +* **github**: split npm jobs and add dependency caching [`2118`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2118) +* **test**: parallel pytest execution [`2133`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2133) + +### Documentation + +* Add installer directions [`2114`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2114) + +### Build + +* Move all build and project configuration to pyproject.toml [`2122`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2122) +* Use relative paths in coverage report [`2125`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2125) +* Remove auto-generated changelog from desktop package [`2126`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2126) + +### Chore + +* Fix licensing-related issues [`2132`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2132) +* Add license headers for projects files [`2130`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2130) + +### BREAKING CHANGES + +* **aggregation-api**: add new endpoint for `economy/mc-all` aggregation [`2092`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2092) + +**Full Changelog**: https://github.com/AntaresSimulatorTeam/AntaREST/compare/v2.17.5...v2.17.6 + v2.17.5 (2024-08-05) -------------------- diff --git a/installer b/installer index e7552a8a66..bd51be05c7 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit e7552a8a66bef72f9e4b8fc6e1b274895f15a180 +Subproject commit bd51be05c7f0f1c634f2cd0c564686ed34b3a6f7 diff --git a/pyproject.toml b/pyproject.toml index 1d01065859..42c259d133 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools"] [project] name = "AntaREST" -version = "2.17.5" +version = "2.17.6" authors = [{name="RTE, Antares Web Team", email="andrea.sgattoni@rte-france.com" }] description="Antares Server" readme = {file = "README.md", content-type = "text/markdown"} @@ -38,8 +38,14 @@ where = ["."] include = ["antarest*"] [tool.mypy] +exclude = "antarest/fastapi_jwt_auth/*" strict = true -files = "antarest/**/*.py" +files = "antarest" +plugins = "pydantic.mypy" + +[[tool.mypy.overrides]] +module = ["antarest/fastapi_jwt_auth.*"] +follow_imports = "skip" [[tool.mypy.overrides]] module = [ @@ -71,7 +77,7 @@ line-length = 120 exclude = "(antares-?launcher/*|alembic/*)" [tool.coverage.run] -omit = ["antarest/tools/cli.py", "antarest/tools/admin.py"] +omit = ["antarest/tools/cli.py", "antarest/tools/admin.py", "antarest/fastapi_jwt_auth/*.py"] relative_files = true # avoids absolute path issues in CI [tool.isort] diff --git a/requirements-dev.txt b/requirements-dev.txt index 5ea6126c6c..973973dc76 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ # Version of Black should match the versions set in `.github/workflows/main.yml` black~=23.7.0 isort~=5.12.0 -mypy~=1.4.1 +mypy~=1.11.1 pyinstaller==5.6.2 pyinstaller-hooks-contrib==2024.6 diff --git a/requirements-test.txt b/requirements-test.txt index 8e408b2677..e72650560c 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,8 +1,11 @@ -r requirements.txt checksumdir~=1.2.0 -pytest~=6.2.5 +pytest~=8.3.0 +pytest-xdist~=3.6.0 pytest-cov~=4.0.0 +pytest-mock~=3.14.0 # In this version DataFrame conversion to Excel is done using 'xlsxwriter' library. # But Excel files reading is done using 'openpyxl' library, during testing only. -openpyxl~=3.1.2 \ No newline at end of file +openpyxl~=3.1.2 +jinja2~=3.1.3 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index eb42c65793..2a7ff60a2d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,18 +1,35 @@ Antares-Launcher~=1.3.2 -antares-study-version~=1.0.3 +antares-study-version==1.0.6 antares-timeseries-generation~=0.1.5 +# When you install `fastapi[all]`, you get FastAPI along with additional dependencies: +# - `uvicorn`: A fast ASGI server commonly used to run FastAPI applications. +# - `pydantic`: A data validation library integrated into FastAPI for defining data models and validating input and output of endpoints. +# - `httpx`: A modern HTTP client library for making HTTP requests from your FastAPI application. +# - `starlette`: The underlying ASGI framework used by FastAPI for handling HTTP requests. +# - `uvloop` (on certain systems): A fast event loop based on uvicorn that improves FastAPI application performance. +# - `python-multipart`: A library for handling multipart data in HTTP requests, commonly used for processing file uploads. +# - `watchdog`: A file watching library used by FastAPI's automatic reloading tool to update the application in real-time when files are modified. +# - `email-validator`: A library for email address validation, used for validating email fields in Pydantic models. +# - `python-dotenv`: A library for managing environment variables, commonly used to load application configurations from `.env` files. + +# We prefer to add only the specific libraries we need for our project +# and **manage their versions** for better control and to avoid unnecessary dependencies. +fastapi~=0.110.3 +uvicorn[standard]~=0.30.6 +pydantic~=2.8.2 +httpx~=0.27.0 +python-multipart~=0.0.9 + alembic~=1.7.5 asgi-ratelimit[redis]==0.7.0 bcrypt~=3.2.0 click~=8.0.3 contextvars~=2.4 -fastapi-jwt-auth~=0.5.0 -fastapi[all]~=0.73.0 filelock~=3.4.2 gunicorn~=20.1.0 -Jinja2~=3.0.3 jsonref~=0.2 +PyJWT~=2.9.0 MarkupSafe~=2.0.1 numpy~=1.22.1 pandas~=1.4.0 @@ -20,18 +37,13 @@ paramiko~=2.12.0 plyer~=2.0.0 psycopg2-binary==2.9.4 py7zr~=0.20.6 -pydantic~=1.9.0 PyQt5~=5.15.6 python-json-logger~=2.0.7 -python-multipart~=0.0.5 PyYAML~=5.4.1; python_version <= '3.9' PyYAML~=5.3.1; python_version > '3.9' redis~=4.1.2 -requests~=2.27.1 SQLAlchemy~=1.4.46 -starlette~=0.17.1 tables==3.6.1; python_version <= '3.8' tables==3.9.2; python_version > '3.8' -typing_extensions~=4.7.1 -uvicorn[standard]~=0.15.0 -xlsxwriter~=3.2.0 +typing_extensions~=4.12.2 +xlsxwriter~=3.2.0 \ No newline at end of file diff --git a/resources/application.yaml b/resources/application.yaml index 6fbdb31f9f..c962d09015 100644 --- a/resources/application.yaml +++ b/resources/application.yaml @@ -26,7 +26,19 @@ launcher: 700: path/to/700 enable_nb_cores_detection: true -root_path: "api" +# See https://fastapi.tiangolo.com/advanced/behind-a-proxy/ +# root path is used when the API is served behind a proxy which +# adds a prefix for clients. +# It does NOT add any prefix to the URLs which fastapi serve. + +# root_path: "api" + + +# Uncomment to serve the API under /api prefix +# (used in standalone mode to emulate the effect of proxy servers +# used in production deployments). + +# api_prefix: "/api" server: worker_threadpool_size: 12 @@ -36,4 +48,7 @@ server: logging: level: INFO - logfile: ./tmp/antarest.log \ No newline at end of file + logfile: ./tmp/antarest.log + +# True to get sqlalchemy logs +debug: False diff --git a/resources/deploy/config.prod.yaml b/resources/deploy/config.prod.yaml index cf9087a2af..9d8d78d56e 100644 --- a/resources/deploy/config.prod.yaml +++ b/resources/deploy/config.prod.yaml @@ -66,6 +66,10 @@ launcher: debug: false +# See https://fastapi.tiangolo.com/advanced/behind-a-proxy/ +# root path is used when the API is served behind a proxy which +# adds a prefix for clients. +# It does NOT add any prefix to the URLs which fastapi serve. root_path: "api" #tasks: diff --git a/resources/deploy/config.yaml b/resources/deploy/config.yaml index 6f3fdf595f..08831198ce 100644 --- a/resources/deploy/config.yaml +++ b/resources/deploy/config.yaml @@ -46,7 +46,8 @@ launcher: debug: false -root_path: "api" +# Serve the API at /api +api_prefix: "/api" server: worker_threadpool_size: 12 diff --git a/resources/empty_study_860.zip b/resources/empty_study_860.zip index 50ee0b283e..1ef7d7bc0a 100644 Binary files a/resources/empty_study_860.zip and b/resources/empty_study_860.zip differ diff --git a/resources/empty_study_870.zip b/resources/empty_study_870.zip index 7838152994..1a06576b52 100644 Binary files a/resources/empty_study_870.zip and b/resources/empty_study_870.zip differ diff --git a/resources/empty_study_880.zip b/resources/empty_study_880.zip index 3667408c59..3e20e25f18 100644 Binary files a/resources/empty_study_880.zip and b/resources/empty_study_880.zip differ diff --git a/resources/templates/.placeholder b/resources/templates/.placeholder deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/scripts/build-front.sh b/scripts/build-front.sh index 87c2db6a50..15c2e0e60f 100755 --- a/scripts/build-front.sh +++ b/scripts/build-front.sh @@ -11,4 +11,3 @@ npm run build -- --mode=desktop cd .. rm -fr resources/webapp cp -r ./webapp/dist/ resources/webapp -cp ./webapp/dist/index.html resources/templates/ diff --git a/scripts/license_checker_and_adder.py b/scripts/license_checker_and_adder.py new file mode 100755 index 0000000000..31139ae87a --- /dev/null +++ b/scripts/license_checker_and_adder.py @@ -0,0 +1,134 @@ +import os +import re +from pathlib import Path +from typing import List + +import click + +# Use to skip subtrees that have their own licenses (forks) +LICENSE_FILE_PATTERN = re.compile("LICENSE.*") + +BACKEND_LICENSE_HEADER = """# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. +""" + + +front_license_path = Path(__file__).resolve().parent.parent / "webapp" / "license-header.js" +FRONTEND_LICENSE_HEADER = front_license_path.read_text() + + +def is_license_file(filename: str) -> bool: + return LICENSE_FILE_PATTERN.match(filename) is not None + + +def check_file(file_path: Path, action: str, license_as_list: List[str], license_to_save: List[str]) -> bool: + file_content = file_path.read_text().splitlines() + n = len(license_as_list) + if len(file_content) >= n and file_content[:n] == license_as_list: + return True + click.echo(f"{file_path} has no valid header.") + new_lines = [] + if action == "fix": + with open(file_path, "r") as f: # doesn't seem really optimal as I read the file twice. + already_licensed = False + lines = f.readlines() + first_line = lines[0].lower() if len(lines) > 0 else [] + if "copyright" in first_line or "license" in first_line: # assumes license follows this + already_licensed = True + if already_licensed: # I don't really know what to do here + raise ValueError(f"File {file_path} already licensed.") + else: + new_lines = license_to_save + lines + if new_lines: + with open(file_path, "w") as f: + f.writelines(new_lines) + + +def check_dir( + cwd: Path, + dir_path: Path, + action: str, + invalid_files: List[Path], + suffixes: List[str], + license_as_list: List[str], + license_to_save: List[str], +) -> None: + _, dirnames, filenames = next(os.walk(dir_path)) + for f in filenames: + if dir_path != cwd and is_license_file(f): + click.echo(f"Found third party license file, skipping folder: {dir_path / f}") + return + + for f in filenames: + file_path = dir_path / f + + if file_path.suffix not in suffixes: + continue + + if not check_file(file_path, action, license_as_list, license_to_save): + invalid_files.append(file_path) + + for d in dirnames: + check_dir(cwd, dir_path / d, action, invalid_files, suffixes, license_as_list, license_to_save) + + +@click.command("license_checker_and_adder") +@click.option( + "--path", + nargs=1, + required=True, + type=click.Path(exists=True, path_type=Path), + help="Path to check", +) +@click.option( + "--action", + nargs=1, + required=False, + default="check", + type=str, + help="Action to realise. Can either be check or fix", +) +def cli(path: Path, action: str) -> None: + if action not in ["check", "check-strict", "fix"]: + raise ValueError(f"Parameter --action should be 'check', 'check-strict' or 'fix' and was '{action}'") + + invalid_files = [] + cwd = Path.cwd() + # --------- infer which files to check and which license to add + suffixes = [".ts", ".tsx"] + license_header = FRONTEND_LICENSE_HEADER + if path.name in ["antarest", "tests"]: + suffixes = [".py"] + license_header = BACKEND_LICENSE_HEADER + license_as_list = license_header.splitlines() + license_to_save = [header + "\n" for header in license_as_list] + ["\n"] + # -------- + check_dir(cwd, path, action, invalid_files, suffixes, license_as_list, license_to_save) + file_count = len(invalid_files) + if file_count > 0: + if action == "fix": + click.echo(f"{file_count} files have been fixed") + else: + click.echo(f"{file_count} files have an invalid header. Use --action=fix to fix them") + if action == "check-strict": + raise ValueError("Some files have invalid headers") + + else: + click.echo("All good !") + + +def main(): + cli(prog_name="cli") + + +if __name__ == "__main__": + main() diff --git a/sonar-project.properties b/sonar-project.properties index 07d21a096d..fa40909147 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -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.17.5 -sonar.coverage.exclusions=antarest/gui.py,antarest/main.py,antarest/singleton_services.py,antarest/worker/archive_worker_service.py,webapp/**/* \ No newline at end of file +sonar.projectVersion=2.17.6 +sonar.coverage.exclusions=antarest/gui.py,antarest/main.py,antarest/singleton_services.py,antarest/worker/archive_worker_service.py,webapp/**/*,,antarest/fastapi_jwt_auth/** \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/cache/__init__.py b/tests/cache/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/cache/__init__.py +++ b/tests/cache/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/cache/test_local_cache.py b/tests/cache/test_local_cache.py index b9fae75ee9..8f8643d2f4 100644 --- a/tests/cache/test_local_cache.py +++ b/tests/cache/test_local_cache.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import time from pathlib import Path from unittest import mock @@ -29,11 +41,11 @@ def test_lifecycle(): id = "some_id" duration = 3600 timeout = int(time.time()) + duration - cache_element = LocalCacheElement(duration=duration, data=config.dict(), timeout=timeout) + cache_element = LocalCacheElement(duration=duration, data=config.model_dump(), timeout=timeout) # PUT - cache.put(id=id, data=config.dict(), duration=duration) + cache.put(id=id, data=config.model_dump(), duration=duration) assert cache.cache[id] == cache_element # GET - assert cache.get(id=id) == config.dict() + assert cache.get(id=id) == config.model_dump() diff --git a/tests/cache/test_redis_cache.py b/tests/cache/test_redis_cache.py index a7c76d07c1..b3d9cabefd 100644 --- a/tests/cache/test_redis_cache.py +++ b/tests/cache/test_redis_cache.py @@ -1,8 +1,20 @@ -import json +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock from antarest.core.cache.business.redis_cache import RedisCache, RedisCacheElement +from antarest.core.serialization import from_json from antarest.study.storage.rawstudy.model.filesystem.config.model import Area, FileStudyTreeConfigDTO @@ -28,18 +40,18 @@ def test_lifecycle(): id = "some_id" redis_key = f"cache:{id}" duration = 3600 - cache_element = RedisCacheElement(duration=duration, data=config.dict()).json() + cache_element = RedisCacheElement(duration=duration, data=config.model_dump()).model_dump_json() # GET redis_client.get.return_value = cache_element - load = json.loads(cache_element) + load = from_json(cache_element) assert cache.get(id=id) == load["data"] redis_client.expire.assert_called_with(redis_key, duration) redis_client.get.assert_called_once_with(redis_key) # PUT duration = 7200 - cache_element = RedisCacheElement(duration=duration, data=config.dict()).json() - cache.put(id=id, data=config.dict(), duration=duration) + cache_element = RedisCacheElement(duration=duration, data=config.model_dump()).model_dump_json() + cache.put(id=id, data=config.model_dump(), duration=duration) redis_client.set.assert_called_once_with(redis_key, cache_element) redis_client.expire.assert_called_with(redis_key, duration) diff --git a/tests/cache/test_service.py b/tests/cache/test_service.py index 5377551a8b..cc833227d0 100644 --- a/tests/cache/test_service.py +++ b/tests/cache/test_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock from antarest.core.cache.business.local_chache import LocalCache diff --git a/tests/conftest.py b/tests/conftest.py index e1a1d69bff..3a074c8b98 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path import pytest diff --git a/tests/conftest_db.py b/tests/conftest_db.py index 925e0fe639..51b63d24af 100644 --- a/tests/conftest_db.py +++ b/tests/conftest_db.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import typing as t diff --git a/tests/conftest_services.py b/tests/conftest_services.py index 59f562e241..24d94acafb 100644 --- a/tests/conftest_services.py +++ b/tests/conftest_services.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ This module provides various pytest fixtures for unit testing the AntaREST application. diff --git a/tests/core/__init__.py b/tests/core/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/core/__init__.py +++ b/tests/core/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/core/assets/__init__.py b/tests/core/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/core/assets/__init__.py +++ b/tests/core/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/core/tasks/__init__.py b/tests/core/tasks/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/core/tasks/__init__.py +++ b/tests/core/tasks/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/core/tasks/test_model.py b/tests/core/tasks/test_model.py index 763aa36db8..8c93ba9c3b 100644 --- a/tests/core/tasks/test_model.py +++ b/tests/core/tasks/test_model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import uuid import pytest diff --git a/tests/core/tasks/test_task_job_service.py b/tests/core/tasks/test_task_job_service.py index 40a463675a..759146cac5 100644 --- a/tests/core/tasks/test_task_job_service.py +++ b/tests/core/tasks/test_task_job_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime from sqlalchemy.orm import Session # type: ignore diff --git a/tests/core/test_auth.py b/tests/core/test_auth.py index 24fda299c5..469ce8a2ee 100644 --- a/tests/core/test_auth.py +++ b/tests/core/test_auth.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock from fastapi import FastAPI diff --git a/tests/core/test_exceptions.py b/tests/core/test_exceptions.py index 86892187a0..9ebdc6aa84 100644 --- a/tests/core/test_exceptions.py +++ b/tests/core/test_exceptions.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.core.exceptions import ReferencedObjectDeletionNotAllowed diff --git a/tests/core/test_file_transfer.py b/tests/core/test_file_transfer.py index 2b0cfff0c6..44cf01e410 100644 --- a/tests/core/test_file_transfer.py +++ b/tests/core/test_file_transfer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime from pathlib import Path from unittest.mock import Mock diff --git a/tests/core/test_jwt.py b/tests/core/test_jwt.py index 61c006d871..603d2b76dc 100644 --- a/tests/core/test_jwt.py +++ b/tests/core/test_jwt.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.core.jwt import JWTGroup, JWTUser from antarest.core.roles import RoleType from antarest.login.model import Group, User diff --git a/tests/core/test_maintenance.py b/tests/core/test_maintenance.py index a0ccad5db9..c6c604d9ca 100644 --- a/tests/core/test_maintenance.py +++ b/tests/core/test_maintenance.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock import pytest diff --git a/tests/core/test_tasks.py b/tests/core/test_tasks.py index cfe36a244e..cb2c635177 100644 --- a/tests/core/test_tasks.py +++ b/tests/core/test_tasks.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import time import typing as t @@ -30,8 +42,8 @@ from antarest.eventbus.business.local_eventbus import LocalEventBus from antarest.eventbus.service import EventBusService from antarest.login.model import User +from antarest.service_creator import SESSION_ARGS from antarest.study.model import RawStudy -from antarest.utils import SESSION_ARGS from antarest.worker.worker import AbstractWorker, WorkerTaskCommand from tests.helpers import with_db_context @@ -107,7 +119,7 @@ def test_service(core_config: Config, event_bus: IEventBus) -> None: "status": TaskStatus.FAILED, "type": None, } - assert res.dict() == expected + assert res.model_dump() == expected # Test Case: add a task that fails and wait for it # ================================================ diff --git a/tests/core/test_utils.py b/tests/core/test_utils.py index 78808aafab..d57ac68d21 100644 --- a/tests/core/test_utils.py +++ b/tests/core/test_utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import zipfile from pathlib import Path diff --git a/tests/core/test_utils_bp.py b/tests/core/test_utils_bp.py index cb9b47618d..b4ae0847ed 100644 --- a/tests/core/test_utils_bp.py +++ b/tests/core/test_utils_bp.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus from pathlib import Path from unittest.mock import Mock diff --git a/tests/core/test_version_info.py b/tests/core/test_version_info.py index daa63e317d..2ad075d9f1 100644 --- a/tests/core/test_version_info.py +++ b/tests/core/test_version_info.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re from unittest.mock import patch diff --git a/tests/core/utils/__init__.py b/tests/core/utils/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/core/utils/__init__.py +++ b/tests/core/utils/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/core/utils/test_extract_zip.py b/tests/core/utils/test_extract_zip.py index 11c3c11ff3..dfbde6bf6d 100644 --- a/tests/core/utils/test_extract_zip.py +++ b/tests/core/utils/test_extract_zip.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import zipfile from pathlib import Path diff --git a/tests/db_statement_recorder.py b/tests/db_statement_recorder.py index c6a1264e03..890205b94f 100644 --- a/tests/db_statement_recorder.py +++ b/tests/db_statement_recorder.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Record SQL statements in memory to diagnose the queries performed by the application. """ diff --git a/tests/eventbus/__init__.py b/tests/eventbus/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/eventbus/__init__.py +++ b/tests/eventbus/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/eventbus/test_local_eventbus.py b/tests/eventbus/test_local_eventbus.py index a42b40a990..571673cbeb 100644 --- a/tests/eventbus/test_local_eventbus.py +++ b/tests/eventbus/test_local_eventbus.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.core.interfaces.eventbus import Event, EventType from antarest.core.model import PermissionInfo, PublicMode from antarest.eventbus.business.local_eventbus import LocalEventBus diff --git a/tests/eventbus/test_redis_event_bus.py b/tests/eventbus/test_redis_event_bus.py index 8e28ab1163..37f69e1fad 100644 --- a/tests/eventbus/test_redis_event_bus.py +++ b/tests/eventbus/test_redis_event_bus.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock from antarest.core.interfaces.eventbus import Event, EventType @@ -17,7 +29,7 @@ def test_lifecycle(): payload="foo", permissions=PermissionInfo(public_mode=PublicMode.READ), ) - serialized = event.json() + serialized = event.model_dump_json() pubsub_mock.get_message.return_value = {"data": serialized} eventbus.push_event(event) redis_client.publish.assert_called_once_with("events", serialized) diff --git a/tests/eventbus/test_service.py b/tests/eventbus/test_service.py index 40db647ca3..4089849db7 100644 --- a/tests/eventbus/test_service.py +++ b/tests/eventbus/test_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Awaitable, Callable, List from unittest.mock import MagicMock, Mock diff --git a/tests/eventbus/test_websocket_manager.py b/tests/eventbus/test_websocket_manager.py index fc512854c8..94500de322 100644 --- a/tests/eventbus/test_websocket_manager.py +++ b/tests/eventbus/test_websocket_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest import IsolatedAsyncioTestCase from unittest.mock import MagicMock, call @@ -25,7 +37,7 @@ async def test_subscriptions(self): await ws_manager.connect(mock_connection, user) assert len(ws_manager.active_connections) == 1 - ws_manager.process_message(subscribe_message.json(), mock_connection) + ws_manager.process_message(subscribe_message.model_dump_json(), mock_connection) connections = ws_manager.active_connections[0] assert len(connections.channel_subscriptions) == 1 assert connections.channel_subscriptions[0] == "foo" @@ -39,7 +51,7 @@ async def test_subscriptions(self): mock_connection.send_text.assert_has_calls([call("msg1"), call("msg2")]) - ws_manager.process_message(unsubscribe_message.json(), mock_connection) + ws_manager.process_message(unsubscribe_message.model_dump_json(), mock_connection) assert len(connections.channel_subscriptions) == 0 ws_manager.disconnect(mock_connection) diff --git a/tests/helpers.py b/tests/helpers.py index d9652b6585..80dd0683a6 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import math import time import uuid diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/__init__.py +++ b/tests/integration/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/assets/__init__.py b/tests/integration/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/integration/assets/__init__.py +++ b/tests/integration/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 64d00e745d..833791850d 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os import typing as t import zipfile diff --git a/tests/integration/filesystem_blueprint/__init__.py b/tests/integration/filesystem_blueprint/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/filesystem_blueprint/__init__.py +++ b/tests/integration/filesystem_blueprint/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py b/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py index ba33b51d9f..ac1e9a36ff 100644 --- a/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py +++ b/tests/integration/filesystem_blueprint/test_filesystem_endpoints.py @@ -1,10 +1,22 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import operator import re -import shutil import typing as t from pathlib import Path +from pytest_mock import MockerFixture from starlette.testclient import TestClient from tests.integration.conftest import RESOURCES_DIR @@ -81,6 +93,7 @@ def test_lifecycle( client: TestClient, user_access_token: str, admin_access_token: str, + mocker: MockerFixture, ) -> None: """ Test the lifecycle of the filesystem endpoints. @@ -90,7 +103,7 @@ def test_lifecycle( caplog: pytest caplog fixture. client: test client (tests.integration.conftest.client_fixture). user_access_token: access token of a classic user (tests.integration.conftest.user_access_token_fixture). - admin_access_token: access token of an admin user (tests.integration.conftest.admin_access_token_fixture). + admin_access_token: access token of an admin user (tests.integration.conftestin_access_token_fixture). """ # NOTE: all the following paths are based on the configuration defined in the app_fixture. archive_dir = tmp_path / "archive_dir" @@ -153,26 +166,25 @@ def test_lifecycle( err_count += 1 # Known filesystem + mocker.patch("shutil.disk_usage", return_value=(100, 200, 300)) res = client.get("/v1/filesystem/ws", headers=user_headers) assert res.status_code == 200, res.json() actual = sorted(res.json(), key=operator.itemgetter("name")) - # Both mount point are in the same filesystem, which is the `tmp_path` filesystem - total_bytes, used_bytes, free_bytes = shutil.disk_usage(tmp_path) expected = [ { "name": "default", "path": str(default_workspace), - "total_bytes": total_bytes, - "used_bytes": used_bytes, - "free_bytes": free_bytes, + "total_bytes": 100, + "used_bytes": 200, + "free_bytes": 300, "message": AnyDiskUsagePercent(), }, { "name": "ext", "path": str(ext_workspace_path), - "total_bytes": total_bytes, - "used_bytes": used_bytes, - "free_bytes": free_bytes, + "total_bytes": 100, + "used_bytes": 200, + "free_bytes": 300, "message": AnyDiskUsagePercent(), }, ] @@ -194,9 +206,9 @@ def test_lifecycle( expected = { "name": "default", "path": str(default_workspace), - "total_bytes": total_bytes, - "used_bytes": used_bytes, - "free_bytes": free_bytes, + "total_bytes": 100, + "used_bytes": 200, + "free_bytes": 300, "message": AnyDiskUsagePercent(), } assert actual == expected diff --git a/tests/integration/filesystem_blueprint/test_model.py b/tests/integration/filesystem_blueprint/test_model.py index 3c21340363..d26bdb02cb 100644 --- a/tests/integration/filesystem_blueprint/test_model.py +++ b/tests/integration/filesystem_blueprint/test_model.py @@ -1,9 +1,23 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import asyncio import datetime import re import shutil from pathlib import Path +from pytest_mock import MockerFixture + from antarest.core.filesystem_blueprint import FileInfoDTO, FilesystemDTO, MountPointDTO @@ -16,7 +30,7 @@ def test_init(self) -> None: "common": "/path/to/workspaces/common_studies", }, } - dto = FilesystemDTO.parse_obj(example) + dto = FilesystemDTO.model_validate(example) assert dto.name == example["name"] assert dto.mount_dirs["default"] == Path(example["mount_dirs"]["default"]) assert dto.mount_dirs["common"] == Path(example["mount_dirs"]["common"]) @@ -32,7 +46,7 @@ def test_init(self) -> None: "free_bytes": 1e9 - 0.6e9, "message": f"{0.6e9 / 1e9:%} used", } - dto = MountPointDTO.parse_obj(example) + dto = MountPointDTO.model_validate(example) assert dto.name == example["name"] assert dto.path == Path(example["path"]) assert dto.total_bytes == example["total_bytes"] @@ -51,15 +65,16 @@ def test_from_path__missing_file(self) -> None: assert dto.free_bytes == 0 assert dto.message.startswith("N/A:"), dto.message - def test_from_path__file(self, tmp_path: Path) -> None: + def test_from_path__file(self, tmp_path: Path, mocker: MockerFixture) -> None: + mocker.patch("shutil.disk_usage", return_value=(100, 200, 300)) + name = "foo" dto = asyncio.run(MountPointDTO.from_path(name, tmp_path)) - total_bytes, used_bytes, free_bytes = shutil.disk_usage(tmp_path) assert dto.name == name assert dto.path == tmp_path - assert dto.total_bytes == total_bytes - assert dto.used_bytes == used_bytes - assert dto.free_bytes == free_bytes + assert dto.total_bytes == 100 + assert dto.used_bytes == 200 + assert dto.free_bytes == 300 assert re.fullmatch(r"\d+(?:\.\d+)?% used", dto.message), dto.message @@ -75,7 +90,7 @@ def test_init(self) -> None: "accessed": "2024-01-11T17:54:09", "message": "OK", } - dto = FileInfoDTO.parse_obj(example) + dto = FileInfoDTO.model_validate(example) assert dto.path == Path(example["path"]) assert dto.file_type == example["file_type"] assert dto.file_count == example["file_count"] diff --git a/tests/integration/launcher_blueprint/__init__.py b/tests/integration/launcher_blueprint/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/launcher_blueprint/__init__.py +++ b/tests/integration/launcher_blueprint/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/launcher_blueprint/test_launcher_local.py b/tests/integration/launcher_blueprint/test_launcher_local.py index aeff69e315..67fc421324 100644 --- a/tests/integration/launcher_blueprint/test_launcher_local.py +++ b/tests/integration/launcher_blueprint/test_launcher_local.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http import pytest @@ -64,10 +76,8 @@ def test_get_launcher_nb_cores( ) assert res.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY, res.json() actual = res.json() - assert actual == { - "description": "Unknown solver configuration: 'unknown'", - "exception": "UnknownSolverConfig", - } + assert actual["description"] == "Input should be 'slurm', 'local' or 'default'" + assert actual["exception"] == "RequestValidationError" def test_get_launcher_time_limit( self, @@ -118,10 +128,8 @@ def test_get_launcher_time_limit( ) assert res.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY, res.json() actual = res.json() - assert actual == { - "description": "Unknown solver configuration: 'unknown'", - "exception": "UnknownSolverConfig", - } + assert actual["description"] == "Input should be 'slurm', 'local' or 'default'" + assert actual["exception"] == "RequestValidationError" def test_jobs_permissions( self, diff --git a/tests/integration/launcher_blueprint/test_solver_versions.py b/tests/integration/launcher_blueprint/test_solver_versions.py index 5c6c0166f9..f4634a497e 100644 --- a/tests/integration/launcher_blueprint/test_solver_versions.py +++ b/tests/integration/launcher_blueprint/test_solver_versions.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Sequence from unittest.mock import patch diff --git a/tests/integration/prepare_proxy.py b/tests/integration/prepare_proxy.py index 0556df8a87..47e5a33294 100644 --- a/tests/integration/prepare_proxy.py +++ b/tests/integration/prepare_proxy.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import typing as t @@ -78,7 +90,7 @@ def copy_study_and_upgrade(self, ref_study_id: str, target_version: int) -> str: task_id = res.json() assert task_id - task = wait_task_completion(self.client, self.user_access_token, task_id, timeout=20) + task = wait_task_completion(self.client, self.user_access_token, task_id, base_timeout=20) assert task.status == TaskStatus.COMPLETED return study_id @@ -161,7 +173,7 @@ def generate_snapshot(self, variant_id: str, denormalize: bool = False, from_scr task_id = res.json() assert task_id - task = wait_task_completion(self.client, self.user_access_token, task_id, timeout=20) + task = wait_task_completion(self.client, self.user_access_token, task_id, base_timeout=20) assert task.status == TaskStatus.COMPLETED def create_area(self, study_id: str, *, name: str, country: str = "FR") -> t.Dict[str, t.Any]: diff --git a/tests/integration/raw_studies_blueprint/__init__.py b/tests/integration/raw_studies_blueprint/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/raw_studies_blueprint/__init__.py +++ b/tests/integration/raw_studies_blueprint/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/raw_studies_blueprint/assets/__init__.py b/tests/integration/raw_studies_blueprint/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/integration/raw_studies_blueprint/assets/__init__.py +++ b/tests/integration/raw_studies_blueprint/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/integration/raw_studies_blueprint/test_aggregate_raw_data.py b/tests/integration/raw_studies_blueprint/test_aggregate_raw_data.py index 591791c8ee..d1b1f304bf 100644 --- a/tests/integration/raw_studies_blueprint/test_aggregate_raw_data.py +++ b/tests/integration/raw_studies_blueprint/test_aggregate_raw_data.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import shutil from pathlib import Path @@ -7,14 +19,7 @@ import pytest from starlette.testclient import TestClient -from antarest.study.business.aggregator_management import ( - MCAllAreasQueryFile, - MCAllLinksQueryFile, - MCIndAreasQueryFile, - MCIndLinksQueryFile, -) from antarest.study.storage.df_download import TableExportFormat -from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency from tests.integration.raw_studies_blueprint.assets import ASSETS_DIR # define the requests parameters for the `economy/mc-ind` outputs aggregation @@ -22,8 +27,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "mc_years": "", "areas_ids": "", "columns_names": "", @@ -33,8 +38,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.DETAILS, - "frequency": MatrixFrequency.HOURLY, + "query_file": "details", + "frequency": "hourly", "mc_years": "1", "areas_ids": "de,fr,it", "columns_names": "", @@ -44,8 +49,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.WEEKLY, + "query_file": "values", + "frequency": "weekly", "mc_years": "1,2", "areas_ids": "", "columns_names": "OP. COST,MRG. PRICE", @@ -55,8 +60,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "mc_years": "2", "areas_ids": "es,fr,de", "columns_names": "", @@ -66,8 +71,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.ANNUAL, + "query_file": "values", + "frequency": "annual", "mc_years": "", "areas_ids": "", "columns_names": "", @@ -77,8 +82,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "columns_names": "COSt,NODu", }, "test-06.result.tsv", @@ -86,8 +91,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.DETAILS, - "frequency": MatrixFrequency.HOURLY, + "query_file": "details", + "frequency": "hourly", "columns_names": "COSt,NODu", }, "test-07.result.tsv", @@ -98,8 +103,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "mc_years": "", "columns_names": "", }, @@ -108,8 +113,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "mc_years": "1", "columns_names": "", }, @@ -118,8 +123,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "mc_years": "1,2", "columns_names": "UCAP LIn.,FLOw qUAD.", }, @@ -128,8 +133,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "mc_years": "1", "links_ids": "de - fr", }, @@ -138,8 +143,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "columns_names": "MArG. COsT,CONG. PRoB +", }, "test-05.result.tsv", @@ -150,8 +155,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "format": "csv", }, "test-01.result.tsv", @@ -159,8 +164,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "format": "tsv", }, "test-01.result.tsv", @@ -168,8 +173,8 @@ ( { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "format": "xlsx", }, "test-01.result.tsv", @@ -180,20 +185,20 @@ INCOHERENT_REQUESTS_BODIES__IND = [ { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "mc_years": "123456789", }, { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "columns_names": "fake_col", }, { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "links_ids": "fake_id", }, ] @@ -202,17 +207,17 @@ { "output_id": "20201014-1425eco-goodbye", "query_file": "fake_query_file", - "frequency": MatrixFrequency.HOURLY, + "frequency": "hourly", }, { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, + "query_file": "values", "frequency": "fake_frequency", }, { "output_id": "20201014-1425eco-goodbye", - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "format": "fake_format", }, ] @@ -222,8 +227,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "areas_ids": "", "columns_names": "", }, @@ -232,8 +237,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.DETAILS, - "frequency": MatrixFrequency.MONTHLY, + "query_file": "details", + "frequency": "monthly", "areas_ids": "de,fr,it", "columns_names": "", }, @@ -242,8 +247,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "areas_ids": "", "columns_names": "OP. CoST,MRG. PrICE", }, @@ -252,8 +257,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "areas_ids": "es,fr,de", "columns_names": "", }, @@ -262,8 +267,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.MONTHLY, + "query_file": "values", + "frequency": "monthly", "areas_ids": "", "columns_names": "", }, @@ -272,8 +277,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.ID, - "frequency": MatrixFrequency.DAILY, + "query_file": "id", + "frequency": "daily", "areas_ids": "", "columns_names": "", }, @@ -282,8 +287,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "columns_names": "COsT,NoDU", }, "test-07-all.result.tsv", @@ -291,8 +296,8 @@ ( { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.DETAILS, - "frequency": MatrixFrequency.MONTHLY, + "query_file": "details", + "frequency": "monthly", "columns_names": "COsT,NoDU", }, "test-08-all.result.tsv", @@ -303,8 +308,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "columns_names": "", }, "test-01-all.result.tsv", @@ -312,8 +317,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.MONTHLY, + "query_file": "values", + "frequency": "monthly", "columns_names": "", }, "test-02-all.result.tsv", @@ -321,8 +326,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "columns_names": "", }, "test-03-all.result.tsv", @@ -330,8 +335,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.MONTHLY, + "query_file": "values", + "frequency": "monthly", "links_ids": "de - fr", }, "test-04-all.result.tsv", @@ -339,8 +344,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.ID, - "frequency": MatrixFrequency.DAILY, + "query_file": "id", + "frequency": "daily", "links_ids": "", }, "test-05-all.result.tsv", @@ -348,8 +353,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "columns_names": "MARG. COsT,CONG. ProB +", }, "test-06-all.result.tsv", @@ -360,8 +365,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "format": "csv", }, "test-01-all.result.tsv", @@ -369,8 +374,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "format": "tsv", }, "test-01-all.result.tsv", @@ -378,8 +383,8 @@ ( { "output_id": "20241807-1540eco-extra-outputs", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "format": "xlsx", }, "test-01-all.result.tsv", @@ -390,19 +395,19 @@ INCOHERENT_REQUESTS_BODIES__ALL = [ { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", }, { "output_id": "20201014-1427eco", - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "columns_names": "fake_col", }, { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.MONTHLY, + "query_file": "values", + "frequency": "monthly", "links_ids": "fake_id", }, ] @@ -411,17 +416,17 @@ { "output_id": "20201014-1427eco", "query_file": "fake_query_file", - "frequency": MatrixFrequency.MONTHLY, + "frequency": "monthly", }, { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, + "query_file": "values", "frequency": "fake_frequency", }, { "output_id": "20201014-1427eco", - "query_file": MCAllAreasQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "format": "fake_format", }, ] @@ -449,7 +454,7 @@ def test_area_aggregation( res = client.get(f"/v1/studies/{internal_study_id}/areas/aggregate/mc-ind/{output_id}", params=params) assert res.status_code == 200, res.json() content = io.BytesIO(res.content) - df = pd.read_csv(content, index_col=0, sep=",") + df = pd.read_csv(content, sep=",") resource_file = ASSETS_DIR.joinpath(f"aggregate_areas_raw_data/{expected_result_filename}") resource_file.parent.mkdir(exist_ok=True, parents=True) if not resource_file.exists(): @@ -478,7 +483,7 @@ def test_links_aggregation( res = client.get(f"/v1/studies/{internal_study_id}/links/aggregate/mc-ind/{output_id}", params=params) assert res.status_code == 200, res.json() content = io.BytesIO(res.content) - df = pd.read_csv(content, index_col=0, sep=",") + df = pd.read_csv(content, sep=",") resource_file = ASSETS_DIR.joinpath(f"aggregate_links_raw_data/{expected_result_filename}") resource_file.parent.mkdir(exist_ok=True, parents=True) if not resource_file.exists(): @@ -509,11 +514,11 @@ def test_different_formats( content = io.BytesIO(res.content) export_format = params["format"] if export_format == TableExportFormat.CSV.value: - df = pd.read_csv(content, index_col=0, sep=",") + df = pd.read_csv(content, sep=",") elif export_format == TableExportFormat.TSV.value: - df = pd.read_csv(content, index_col=0, sep="\t") + df = pd.read_csv(content, sep="\t") else: - df = pd.read_excel(content, index_col=0) # type: ignore + df = pd.read_excel(content) # type: ignore resource_file = ASSETS_DIR.joinpath(f"aggregate_links_raw_data/{expected_result_filename}") resource_file.parent.mkdir(exist_ok=True, parents=True) if not resource_file.exists(): @@ -537,9 +542,7 @@ def test_aggregation_with_incoherent_bodies( output_id = params.pop("output_id") res = client.get(f"/v1/studies/{internal_study_id}/links/aggregate/mc-ind/{output_id}", params=params) assert res.status_code == 200, res.json() - content = io.BytesIO(res.content) - df = pd.read_csv(content, index_col=0, sep=",") - assert df.empty + assert res.content.strip() == b"" def test_wrongly_typed_request(self, client: TestClient, user_access_token: str, internal_study_id: str): """ @@ -562,8 +565,8 @@ def test_aggregation_with_wrong_output(self, client: TestClient, user_access_tok res = client.get( f"/v1/studies/{internal_study_id}/areas/aggregate/mc-ind/unknown_id", params={ - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", }, ) assert res.status_code == 404, res.json() @@ -574,8 +577,8 @@ def test_aggregation_with_wrong_output(self, client: TestClient, user_access_tok res = client.get( f"/v1/studies/{internal_study_id}/links/aggregate/mc-ind/unknown_id", params={ - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", }, ) assert res.status_code == 404, res.json() @@ -592,27 +595,25 @@ def test_empty_columns(self, client: TestClient, user_access_token: str, interna res = client.get( f"/v1/studies/{internal_study_id}/areas/aggregate/mc-ind/20201014-1425eco-goodbye", params={ - "query_file": MCIndAreasQueryFile.DETAILS, - "frequency": MatrixFrequency.HOURLY, + "query_file": "details", + "frequency": "hourly", "columns_names": "fake_col", }, ) assert res.status_code == 200, res.json() - df = pd.read_csv(io.BytesIO(res.content), index_col=0, sep=",") - assert df.empty + assert res.content.strip() == b"" # test for links res = client.get( f"/v1/studies/{internal_study_id}/links/aggregate/mc-ind/20201014-1425eco-goodbye", params={ - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", "columns_names": "fake_col", }, ) assert res.status_code == 200, res.json() - df = pd.read_csv(io.BytesIO(res.content), index_col=0, sep=",") - assert df.empty + assert res.content.strip() == b"" def test_non_existing_folder( self, tmp_path: Path, client: TestClient, user_access_token: str, internal_study_id: str @@ -628,7 +629,7 @@ def test_non_existing_folder( shutil.rmtree(mc_ind_folder) res = client.get( f"/v1/studies/{internal_study_id}/areas/aggregate/mc-ind/20201014-1425eco-goodbye", - params={"query_file": MCIndAreasQueryFile.VALUES, "frequency": MatrixFrequency.HOURLY}, + params={"query_file": "values", "frequency": "hourly"}, ) assert res.status_code == 404, res.json() assert "economy/mc-ind" in res.json()["description"] @@ -657,7 +658,7 @@ def test_area_aggregation( res = client.get(f"/v1/studies/{internal_study_id}/areas/aggregate/mc-all/{output_id}", params=params) assert res.status_code == 200, res.json() content = io.BytesIO(res.content) - df = pd.read_csv(content, index_col=0, sep=",") + df = pd.read_csv(content, sep=",") resource_file = ASSETS_DIR.joinpath(f"aggregate_areas_raw_data/{expected_result_filename}") resource_file.parent.mkdir(exist_ok=True, parents=True) if not resource_file.exists(): @@ -686,7 +687,7 @@ def test_links_aggregation( res = client.get(f"/v1/studies/{internal_study_id}/links/aggregate/mc-all/{output_id}", params=params) assert res.status_code == 200, res.json() content = io.BytesIO(res.content) - df = pd.read_csv(content, index_col=0, sep=",") + df = pd.read_csv(content, sep=",") resource_file = ASSETS_DIR.joinpath(f"aggregate_links_raw_data/{expected_result_filename}") resource_file.parent.mkdir(exist_ok=True, parents=True) if not resource_file.exists(): @@ -717,11 +718,11 @@ def test_different_formats( content = io.BytesIO(res.content) export_format = params["format"] if export_format == TableExportFormat.CSV.value: - df = pd.read_csv(content, index_col=0, sep=",") + df = pd.read_csv(content, sep=",") elif export_format == TableExportFormat.TSV.value: - df = pd.read_csv(content, index_col=0, sep="\t") + df = pd.read_csv(content, sep="\t") else: - df = pd.read_excel(content, index_col=0) # type: ignore + df = pd.read_excel(content) # type: ignore resource_file = ASSETS_DIR.joinpath(f"aggregate_links_raw_data/{expected_result_filename}") resource_file.parent.mkdir(exist_ok=True, parents=True) if not resource_file.exists(): @@ -745,9 +746,7 @@ def test_aggregation_with_incoherent_bodies( output_id = params.pop("output_id") res = client.get(f"/v1/studies/{internal_study_id}/links/aggregate/mc-all/{output_id}", params=params) assert res.status_code == 200, res.json() - content = io.BytesIO(res.content) - df = pd.read_csv(content, index_col=0, sep=",") - assert df.empty + assert res.content.strip() == b"" def test_wrongly_typed_request(self, client: TestClient, user_access_token: str, internal_study_id: str): """ @@ -770,8 +769,8 @@ def test_aggregation_with_wrong_output(self, client: TestClient, user_access_tok res = client.get( f"/v1/studies/{internal_study_id}/areas/aggregate/mc-all/unknown_id", params={ - "query_file": MCIndAreasQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", }, ) assert res.status_code == 404, res.json() @@ -782,8 +781,8 @@ def test_aggregation_with_wrong_output(self, client: TestClient, user_access_tok res = client.get( f"/v1/studies/{internal_study_id}/links/aggregate/mc-all/unknown_id", params={ - "query_file": MCIndLinksQueryFile.VALUES, - "frequency": MatrixFrequency.HOURLY, + "query_file": "values", + "frequency": "hourly", }, ) assert res.status_code == 404, res.json() @@ -801,27 +800,25 @@ def test_empty_columns(self, client: TestClient, user_access_token: str, interna res = client.get( f"/v1/studies/{internal_study_id}/areas/aggregate/mc-all/20201014-1427eco", params={ - "query_file": MCAllAreasQueryFile.DETAILS, - "frequency": MatrixFrequency.MONTHLY, + "query_file": "details", + "frequency": "monthly", "columns_names": "fake_col", }, ) assert res.status_code == 200, res.json() - df = pd.read_csv(io.BytesIO(res.content), index_col=0, sep=",") - assert df.empty + assert res.content.strip() == b"" # test for links res = client.get( f"/v1/studies/{internal_study_id}/links/aggregate/mc-all/20241807-1540eco-extra-outputs", params={ - "query_file": MCAllLinksQueryFile.VALUES, - "frequency": MatrixFrequency.DAILY, + "query_file": "values", + "frequency": "daily", "columns_names": "fake_col", }, ) assert res.status_code == 200, res.json() - df = pd.read_csv(io.BytesIO(res.content), index_col=0, sep=",") - assert df.empty + assert res.content.strip() == b"" def test_non_existing_folder( self, tmp_path: Path, client: TestClient, user_access_token: str, internal_study_id: str @@ -835,7 +832,7 @@ def test_non_existing_folder( shutil.rmtree(mc_all_path) res = client.get( f"/v1/studies/{internal_study_id}/links/aggregate/mc-all/20241807-1540eco-extra-outputs", - params={"query_file": MCAllLinksQueryFile.VALUES, "frequency": MatrixFrequency.DAILY}, + params={"query_file": "values", "frequency": "daily"}, ) assert res.status_code == 404, res.json() assert "economy/mc-all" in res.json()["description"] diff --git a/tests/integration/raw_studies_blueprint/test_download_matrices.py b/tests/integration/raw_studies_blueprint/test_download_matrices.py index c491108f5c..499bd8b587 100644 --- a/tests/integration/raw_studies_blueprint/test_download_matrices.py +++ b/tests/integration/raw_studies_blueprint/test_download_matrices.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import io import typing as t @@ -41,7 +53,7 @@ def copy_upgrade_study(self, ref_study_id, target_version=820): task_id = res.json() assert task_id - task = wait_task_completion(self.client, self.user_access_token, task_id, timeout=20) + task = wait_task_completion(self.client, self.user_access_token, task_id, base_timeout=20) assert task.status == TaskStatus.COMPLETED return study_820_id @@ -79,7 +91,7 @@ def generate_snapshot(self, variant_id: str, denormalize=False, from_scratch=Tru task_id = res.json() assert task_id - task = wait_task_completion(self.client, self.user_access_token, task_id, timeout=20) + task = wait_task_completion(self.client, self.user_access_token, task_id, base_timeout=20) assert task.status == TaskStatus.COMPLETED def create_area(self, parent_id, *, name: str, country: str = "FR") -> str: @@ -347,7 +359,7 @@ def test_download_matrices(self, client: TestClient, user_access_token: str, int for export_format in ["tsv", "xlsx"]: res = client.get( f"/v1/studies/{study_860_id}/raw/download", - params={"path": "input/hydro/series/de/mingen", "format": {export_format}}, + params={"path": "input/hydro/series/de/mingen", "format": export_format}, headers=user_headers, ) assert res.status_code == 200 diff --git a/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py b/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py index e55929c97a..8859a56469 100644 --- a/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py +++ b/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http import io import itertools @@ -252,3 +264,66 @@ def test_get_study( headers=headers, ) assert res.status_code == 200, f"Error for path={path} and depth={depth}" + + +def test_delete_raw(client: TestClient, user_access_token: str, internal_study_id: str) -> None: + client.headers = {"Authorization": f"Bearer {user_access_token}"} + + # ============================= + # SET UP + NOMINAL CASES + # ============================= + + content = io.BytesIO(b"This is the end!") + file_1_path = "user/file_1.txt" + file_2_path = "user/folder/file_2.txt" + file_3_path = "user/folder_2/file_3.txt" + for f in [file_1_path, file_2_path, file_3_path]: + # Creates a file / folder inside user folder. + res = client.put( + f"/v1/studies/{internal_study_id}/raw", params={"path": f, "create_missing": True}, files={"file": content} + ) + assert res.status_code == 204, res.json() + + # Deletes the file / folder + if f == file_2_path: + f = "user/folder" + res = client.delete(f"/v1/studies/{internal_study_id}/raw?path={f}") + assert res.status_code == 200 + # Asserts it doesn't exist anymore + res = client.get(f"/v1/studies/{internal_study_id}/raw?path={f}") + assert res.status_code == 404 + assert "not a child of" in res.json()["description"] + + # checks debug view + res = client.get(f"/v1/studies/{internal_study_id}/raw?path=&depth=-1") + assert res.status_code == 200 + tree = res.json()["user"] + if f == file_3_path: + # asserts the folder that wasn't deleted is still here. + assert list(tree.keys()) == ["expansion", "folder_2"] + assert tree["folder_2"] == {} + else: + # asserts deleted files cannot be seen inside the debug view + assert list(tree.keys()) == ["expansion"] + + # ============================= + # ERRORS + # ============================= + + # try to delete expansion folder + res = client.delete(f"/v1/studies/{internal_study_id}/raw?path=/user/expansion") + assert res.status_code == 403 + assert res.json()["exception"] == "FileDeletionNotAllowed" + assert "you are not allowed to delete this resource" in res.json()["description"] + + # try to delete a file which isn't inside the 'User' folder + res = client.delete(f"/v1/studies/{internal_study_id}/raw?path=/input/thermal") + assert res.status_code == 403 + assert res.json()["exception"] == "FileDeletionNotAllowed" + assert "the targeted data isn't inside the 'User' folder" in res.json()["description"] + + # With a path that doesn't exist + res = client.delete(f"/v1/studies/{internal_study_id}/raw?path=user/fake_folder/fake_file.txt") + assert res.status_code == 403 + assert res.json()["exception"] == "FileDeletionNotAllowed" + assert "the given path doesn't exist" in res.json()["description"] diff --git a/tests/integration/studies_blueprint/__init__.py b/tests/integration/studies_blueprint/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/studies_blueprint/__init__.py +++ b/tests/integration/studies_blueprint/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/studies_blueprint/assets/__init__.py b/tests/integration/studies_blueprint/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/integration/studies_blueprint/assets/__init__.py +++ b/tests/integration/studies_blueprint/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json b/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json index 80ffa29e32..1e0f3ada52 100644 --- a/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json +++ b/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json @@ -38,22 +38,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -77,22 +62,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -116,22 +86,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -155,22 +110,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -194,22 +134,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -233,22 +158,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -272,22 +182,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -311,22 +206,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -350,22 +230,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], @@ -413,22 +278,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -452,22 +302,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -491,22 +326,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -530,22 +350,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -569,22 +374,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -608,22 +398,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -647,22 +422,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -686,22 +446,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -725,22 +470,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], @@ -788,22 +518,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -827,22 +542,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -866,22 +566,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -905,22 +590,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -944,22 +614,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -983,22 +638,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -1022,22 +662,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -1061,22 +686,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -1100,22 +710,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], @@ -1151,22 +746,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -1190,22 +770,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -1229,22 +794,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -1268,22 +818,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -1307,22 +842,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -1346,22 +866,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -1385,22 +890,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -1424,22 +914,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -1463,22 +938,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], diff --git a/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json b/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json index a77fa18a58..7e449747e4 100644 --- a/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json +++ b/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json @@ -38,22 +38,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -77,22 +62,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -116,22 +86,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -155,22 +110,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -194,22 +134,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -233,22 +158,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -272,22 +182,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -311,22 +206,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -350,22 +230,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], @@ -413,22 +278,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -452,22 +302,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -491,22 +326,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -530,22 +350,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -569,22 +374,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -608,22 +398,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -647,22 +422,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -686,22 +446,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -725,22 +470,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], @@ -788,22 +518,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -827,22 +542,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -866,22 +566,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -905,22 +590,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -944,22 +614,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -983,22 +638,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -1022,22 +662,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -1061,22 +686,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -1100,22 +710,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], @@ -1151,22 +746,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 10.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "02_wind_on", @@ -1190,22 +770,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 20.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "03_wind_off", @@ -1229,22 +794,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 30.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "04_res", @@ -1268,22 +818,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 40.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "05_nuclear", @@ -1307,22 +842,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 50.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "06_coal", @@ -1346,22 +866,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 60.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "07_gas", @@ -1385,22 +890,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 70.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "08_non-res", @@ -1424,22 +914,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 80.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 }, { "id": "09_hydro_pump", @@ -1463,22 +938,7 @@ "fixed-cost": 0.0, "startup-cost": 0.0, "market-bid-cost": 90.0, - "co2": 0.0, - "nh3": 0.0, - "so2": 0.0, - "nox": 0.0, - "pm2_5": 0.0, - "pm5": 0.0, - "pm10": 0.0, - "nmvoc": 0.0, - "op1": 0.0, - "op2": 0.0, - "op3": 0.0, - "op4": 0.0, - "op5": 0.0, - "costgeneration": "SetManually", - "efficiency": 100.0, - "variableomcost": 0.0 + "co2": 0.0 } ], "renewables": [], diff --git a/tests/integration/studies_blueprint/test_comments.py b/tests/integration/studies_blueprint/test_comments.py index 39ce84e35b..b83cc134b7 100644 --- a/tests/integration/studies_blueprint/test_comments.py +++ b/tests/integration/studies_blueprint/test_comments.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import time from xml.etree import ElementTree @@ -26,12 +38,9 @@ def test_raw_study( This test verifies that we can retrieve and modify the comments of a study. It also performs performance measurements and analyzes. """ - + client.headers = {"Authorization": f"Bearer {user_access_token}"} # Get the comments of the study and compare with the expected file - res = client.get( - f"/v1/studies/{internal_study_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{internal_study_id}/comments") assert res.status_code == 200, res.json() actual = res.json() actual_xml = ElementTree.parse(io.StringIO(actual)).getroot() @@ -40,10 +49,7 @@ def test_raw_study( # Ensure the duration is relatively short start = time.time() - res = client.get( - f"/v1/studies/{internal_study_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{internal_study_id}/comments") assert res.status_code == 200, res.json() duration = time.time() - start assert 0 <= duration <= 0.1, f"Duration is {duration} seconds" @@ -51,16 +57,12 @@ def test_raw_study( # Update the comments of the study res = client.put( f"/v1/studies/{internal_study_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, json={"comments": "Ceci est un commentaire en français."}, ) assert res.status_code == 204, res.json() # Get the comments of the study and compare with the expected file - res = client.get( - f"/v1/studies/{internal_study_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{internal_study_id}/comments") assert res.status_code == 200, res.json() assert res.json() == "Ceci est un commentaire en français." @@ -74,10 +76,10 @@ def test_variant_study( This test verifies that we can retrieve and modify the comments of a VARIANT study. It also performs performance measurements and analyzes. """ + client.headers = {"Authorization": f"Bearer {user_access_token}"} # First, we create a copy of the study, and we convert it to a managed study. res = client.post( f"/v1/studies/{internal_study_id}/copy", - headers={"Authorization": f"Bearer {user_access_token}"}, params={"dest": "default", "with_outputs": False, "use_task": False}, # type: ignore ) assert res.status_code == 201, res.json() @@ -85,20 +87,13 @@ def test_variant_study( assert base_study_id is not None # Then, we create a new variant of the base study - res = client.post( - f"/v1/studies/{base_study_id}/variants", - headers={"Authorization": f"Bearer {user_access_token}"}, - params={"name": "Variant XYZ"}, - ) + res = client.post(f"/v1/studies/{base_study_id}/variants", params={"name": "Variant XYZ"}) assert res.status_code == 200, res.json() # should be CREATED variant_id = res.json() assert variant_id is not None # Get the comments of the study and compare with the expected file - res = client.get( - f"/v1/studies/{variant_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/comments") assert res.status_code == 200, res.json() actual = res.json() actual_xml = ElementTree.parse(io.StringIO(actual)).getroot() @@ -107,10 +102,7 @@ def test_variant_study( # Ensure the duration is relatively short start = time.time() - res = client.get( - f"/v1/studies/{variant_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/comments") assert res.status_code == 200, res.json() duration = time.time() - start assert 0 <= duration <= 0.3, f"Duration is {duration} seconds" @@ -118,15 +110,11 @@ def test_variant_study( # Update the comments of the study res = client.put( f"/v1/studies/{variant_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, json={"comments": "Ceci est un commentaire en français."}, ) assert res.status_code == 204, res.json() # Get the comments of the study and compare with the expected file - res = client.get( - f"/v1/studies/{variant_id}/comments", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/comments") assert res.status_code == 200, res.json() assert res.json() == "Ceci est un commentaire en français." diff --git a/tests/integration/studies_blueprint/test_disk_usage.py b/tests/integration/studies_blueprint/test_disk_usage.py index d2257a40fd..6958667863 100644 --- a/tests/integration/studies_blueprint/test_disk_usage.py +++ b/tests/integration/studies_blueprint/test_disk_usage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from starlette.testclient import TestClient @@ -69,7 +81,7 @@ def test_disk_usage_endpoint( # Wait for task completion res = client.get(f"/v1/tasks/{task_id}", headers=user_headers, params={"wait_for_completion": True}) assert res.status_code == 200 - task_result = TaskDTO.parse_obj(res.json()) + task_result = TaskDTO.model_validate(res.json()) assert task_result.status == TaskStatus.COMPLETED assert task_result.result is not None assert task_result.result.success diff --git a/tests/integration/studies_blueprint/test_get_studies.py b/tests/integration/studies_blueprint/test_get_studies.py index af8f790f20..8e94e15d92 100644 --- a/tests/integration/studies_blueprint/test_get_studies.py +++ b/tests/integration/studies_blueprint/test_get_studies.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import operator import re @@ -1471,7 +1483,7 @@ def test_get_studies__invalid_parameters( res = client.get(STUDIES_URL, headers=headers, params={"sortBy": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"not a valid enumeration member", description), f"{description=}" + assert re.search("Input should be", description), f"{description=}" # Invalid `pageNb` parameter (negative integer) res = client.get(STUDIES_URL, headers=headers, params={"pageNb": -1}) @@ -1483,7 +1495,7 @@ def test_get_studies__invalid_parameters( res = client.get(STUDIES_URL, headers=headers, params={"pageNb": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"not a valid integer", description), f"{description=}" + assert re.search(r"should be a valid integer", description), f"{description=}" # Invalid `pageSize` parameter (negative integer) res = client.get(STUDIES_URL, headers=headers, params={"pageSize": -1}) @@ -1495,43 +1507,43 @@ def test_get_studies__invalid_parameters( res = client.get(STUDIES_URL, headers=headers, params={"pageSize": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"not a valid integer", description), f"{description=}" + assert re.search(r"should be a valid integer", description), f"{description=}" # Invalid `managed` parameter (not a boolean) res = client.get(STUDIES_URL, headers=headers, params={"managed": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"could not be parsed to a boolean", description), f"{description=}" + assert re.search(r"should be a valid boolean", description), f"{description=}" # Invalid `archived` parameter (not a boolean) res = client.get(STUDIES_URL, headers=headers, params={"archived": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"could not be parsed to a boolean", description), f"{description=}" + assert re.search(r"should be a valid boolean", description), f"{description=}" # Invalid `variant` parameter (not a boolean) res = client.get(STUDIES_URL, headers=headers, params={"variant": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"could not be parsed to a boolean", description), f"{description=}" + assert re.search(r"should be a valid boolean", description), f"{description=}" # Invalid `versions` parameter (not a list of integers) res = client.get(STUDIES_URL, headers=headers, params={"versions": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"string does not match regex", description), f"{description=}" + assert re.search(r"String should match pattern", description), f"{description=}" # Invalid `users` parameter (not a list of integers) res = client.get(STUDIES_URL, headers=headers, params={"users": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"string does not match regex", description), f"{description=}" + assert re.search(r"String should match pattern", description), f"{description=}" # Invalid `exists` parameter (not a boolean) res = client.get(STUDIES_URL, headers=headers, params={"exists": "invalid"}) assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] - assert re.search(r"could not be parsed to a boolean", description), f"{description=}" + assert re.search(r"should be a valid boolean", description), f"{description=}" def test_studies_counting(client: TestClient, admin_access_token: str, user_access_token: str) -> None: diff --git a/tests/integration/studies_blueprint/test_study_matrix_index.py b/tests/integration/studies_blueprint/test_study_matrix_index.py index 7821ee6151..759b43131b 100644 --- a/tests/integration/studies_blueprint/test_study_matrix_index.py +++ b/tests/integration/studies_blueprint/test_study_matrix_index.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from starlette.testclient import TestClient diff --git a/tests/integration/studies_blueprint/test_synthesis.py b/tests/integration/studies_blueprint/test_synthesis.py index 2b5205824a..d67e0f60a7 100644 --- a/tests/integration/studies_blueprint/test_synthesis.py +++ b/tests/integration/studies_blueprint/test_synthesis.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import sys import time diff --git a/tests/integration/studies_blueprint/test_update_tags.py b/tests/integration/studies_blueprint/test_update_tags.py index 9ee37c7d70..fd9005a98a 100644 --- a/tests/integration/studies_blueprint/test_update_tags.py +++ b/tests/integration/studies_blueprint/test_update_tags.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from starlette.testclient import TestClient @@ -16,14 +28,10 @@ def test_update_tags( This test verifies that we can update the tags of a study. It also tests the tags normalization. """ - + client.headers = {"Authorization": f"Bearer {user_access_token}"} # Classic usage: set some tags to a study study_tags = ["Tag1", "Tag2"] - res = client.put( - f"/v1/studies/{internal_study_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"tags": study_tags}, - ) + res = client.put(f"/v1/studies/{internal_study_id}", json={"tags": study_tags}) assert res.status_code == 200, res.json() actual = res.json() assert set(actual["tags"]) == set(study_tags) @@ -32,11 +40,7 @@ def test_update_tags( # - "Tag1" is preserved, but with the same case as the existing one. # - "Tag2" is replaced by "Tag3". study_tags = ["tag1", "Tag3"] - res = client.put( - f"/v1/studies/{internal_study_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"tags": study_tags}, - ) + res = client.put(f"/v1/studies/{internal_study_id}", json={"tags": study_tags}) assert res.status_code == 200, res.json() actual = res.json() assert set(actual["tags"]) != set(study_tags) # not the same case @@ -45,22 +49,14 @@ def test_update_tags( # String normalization: whitespaces are stripped and # consecutive whitespaces are replaced by a single one. study_tags = [" \xa0Foo \t Bar \n ", " \t Baz\xa0\xa0"] - res = client.put( - f"/v1/studies/{internal_study_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"tags": study_tags}, - ) + res = client.put(f"/v1/studies/{internal_study_id}", json={"tags": study_tags}) assert res.status_code == 200, res.json() actual = res.json() assert set(actual["tags"]) == {"Foo Bar", "Baz"} # We can have symbols in the tags study_tags = ["Foo-Bar", ":Baz%"] - res = client.put( - f"/v1/studies/{internal_study_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"tags": study_tags}, - ) + res = client.put(f"/v1/studies/{internal_study_id}", json={"tags": study_tags}) assert res.status_code == 200, res.json() actual = res.json() assert set(actual["tags"]) == {"Foo-Bar", ":Baz%"} @@ -71,13 +67,10 @@ def test_update_tags__invalid_tags( user_access_token: str, internal_study_id: str, ) -> None: + client.headers = {"Authorization": f"Bearer {user_access_token}"} # We cannot have empty tags study_tags = [""] - res = client.put( - f"/v1/studies/{internal_study_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"tags": study_tags}, - ) + res = client.put(f"/v1/studies/{internal_study_id}", json={"tags": study_tags}) assert res.status_code == 422, res.json() description = res.json()["description"] assert "Tag cannot be empty" in description @@ -85,11 +78,7 @@ def test_update_tags__invalid_tags( # We cannot have tags longer than 40 characters study_tags = ["very long tags, very long tags, very long tags"] assert len(study_tags[0]) > 40 - res = client.put( - f"/v1/studies/{internal_study_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"tags": study_tags}, - ) + res = client.put(f"/v1/studies/{internal_study_id}", json={"tags": study_tags}) assert res.status_code == 422, res.json() description = res.json()["description"] assert "Tag is too long" in description diff --git a/tests/integration/study_data_blueprint/__init__.py b/tests/integration/study_data_blueprint/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/study_data_blueprint/__init__.py +++ b/tests/integration/study_data_blueprint/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/study_data_blueprint/test_advanced_parameters.py b/tests/integration/study_data_blueprint/test_advanced_parameters.py index 4aff92b0cd..7b76ee0c87 100644 --- a/tests/integration/study_data_blueprint/test_advanced_parameters.py +++ b/tests/integration/study_data_blueprint/test_advanced_parameters.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus import pytest @@ -96,7 +108,7 @@ def test_set_advanced_parameters_values( ) assert res.status_code == 422 assert res.json()["exception"] == "RequestValidationError" - assert res.json()["description"] == "Invalid value: fake_correlation" + assert res.json()["description"] == "Value error, Invalid value: fake_correlation" obj = {"unitCommitmentMode": "milp"} res = client.put( diff --git a/tests/integration/study_data_blueprint/test_binding_constraints.py b/tests/integration/study_data_blueprint/test_binding_constraints.py index 64e839c6fa..c5e8d17b5b 100644 --- a/tests/integration/study_data_blueprint/test_binding_constraints.py +++ b/tests/integration/study_data_blueprint/test_binding_constraints.py @@ -1,10 +1,22 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import time import numpy as np import pandas as pd import pytest -from requests.exceptions import HTTPError +from httpx._exceptions import HTTPError from starlette.testclient import TestClient from antarest.study.business.binding_constraint_management import ClusterTerm, ConstraintTerm, LinkTerm @@ -383,7 +395,7 @@ def test_lifecycle__nominal(self, client: TestClient, user_access_token: str, st assert res.status_code == 422, res.json() assert res.json() == { "body": {"data": {}, "id": f"{area1_id}.{cluster_id}"}, - "description": "field required", + "description": "Field required", "exception": "RequestValidationError", } diff --git a/tests/integration/study_data_blueprint/test_config_general.py b/tests/integration/study_data_blueprint/test_config_general.py index 3084a86b4e..7353814e1b 100644 --- a/tests/integration/study_data_blueprint/test_config_general.py +++ b/tests/integration/study_data_blueprint/test_config_general.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus import pytest @@ -33,7 +45,7 @@ def test_get_general_form_values( "firstJanuary": "Monday", "firstMonth": "january", "firstWeekDay": "Monday", - "horizon": "2030", + "horizon": 2030, "lastDay": 7, "leapYear": False, "mcScenario": True, diff --git a/tests/integration/study_data_blueprint/test_edit_matrix.py b/tests/integration/study_data_blueprint/test_edit_matrix.py index 28953d713b..474b53d4e3 100644 --- a/tests/integration/study_data_blueprint/test_edit_matrix.py +++ b/tests/integration/study_data_blueprint/test_edit_matrix.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from urllib.parse import quote import pytest diff --git a/tests/integration/study_data_blueprint/test_generate_thermal_cluster_timeseries.py b/tests/integration/study_data_blueprint/test_generate_thermal_cluster_timeseries.py index ec26295de6..b328f1b2e4 100644 --- a/tests/integration/study_data_blueprint/test_generate_thermal_cluster_timeseries.py +++ b/tests/integration/study_data_blueprint/test_generate_thermal_cluster_timeseries.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy as np from starlette.testclient import TestClient diff --git a/tests/integration/study_data_blueprint/test_hydro_allocation.py b/tests/integration/study_data_blueprint/test_hydro_allocation.py index 47eb65f39d..6ba223bf45 100644 --- a/tests/integration/study_data_blueprint/test_hydro_allocation.py +++ b/tests/integration/study_data_blueprint/test_hydro_allocation.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http import typing as t diff --git a/tests/integration/study_data_blueprint/test_hydro_correlation.py b/tests/integration/study_data_blueprint/test_hydro_correlation.py index c986ead8de..61a76f76e2 100644 --- a/tests/integration/study_data_blueprint/test_hydro_correlation.py +++ b/tests/integration/study_data_blueprint/test_hydro_correlation.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus from typing import List diff --git a/tests/integration/study_data_blueprint/test_hydro_inflow_structure.py b/tests/integration/study_data_blueprint/test_hydro_inflow_structure.py index f673882752..ec1327093d 100644 --- a/tests/integration/study_data_blueprint/test_hydro_inflow_structure.py +++ b/tests/integration/study_data_blueprint/test_hydro_inflow_structure.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from http import HTTPStatus from unittest.mock import ANY diff --git a/tests/integration/study_data_blueprint/test_playlist.py b/tests/integration/study_data_blueprint/test_playlist.py new file mode 100644 index 0000000000..93bc1c9624 --- /dev/null +++ b/tests/integration/study_data_blueprint/test_playlist.py @@ -0,0 +1,44 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from starlette.testclient import TestClient + + +class TestConfigPlaylist: + """ + Test the end points related to the playlist. + """ + + def test_nominal_case(self, client: TestClient, user_access_token: str): + client.headers = {"Authorization": f"Bearer {user_access_token}"} + + base_study_res = client.post("/v1/studies?name=foo") + study_id = base_study_res.json() + + res = client.get(f"/v1/studies/{study_id}/config/playlist") + assert res.status_code == 200 + assert res.json() is None + + res = client.post(f"/v1/studies/{study_id}/raw?path=settings/generaldata/general/nbyears", json=5) + assert res.status_code == 204 + + res = client.put( + f"/v1/studies/{study_id}/config/playlist", + json={"playlist": [1, 2], "weights": {1: 8.0, 3: 9.0}}, + ) + assert res.status_code == 200 + + res = client.get( + f"/v1/studies/{study_id}/config/playlist", + ) + assert res.status_code == 200 + assert res.json() == {"1": 8.0, "2": 1.0} diff --git a/tests/integration/study_data_blueprint/test_renewable.py b/tests/integration/study_data_blueprint/test_renewable.py index b6c450e8f3..8e3fb8051b 100644 --- a/tests/integration/study_data_blueprint/test_renewable.py +++ b/tests/integration/study_data_blueprint/test_renewable.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ ## End-to-end test of the renewable cluster management. @@ -24,7 +36,6 @@ * validate the consistency of the matrices (and properties) """ -import json import re import typing as t @@ -38,7 +49,7 @@ from antarest.study.storage.rawstudy.model.filesystem.config.renewable import RenewableProperties from tests.integration.utils import wait_task_completion -DEFAULT_PROPERTIES = json.loads(RenewableProperties(name="Dummy").json()) +DEFAULT_PROPERTIES = RenewableProperties(name="Dummy").model_dump(mode="json") DEFAULT_PROPERTIES = {to_camel_case(k): v for k, v in DEFAULT_PROPERTIES.items() if k != "name"} # noinspection SpellCheckingInspection @@ -525,13 +536,10 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var In this test, we want to check that renewable clusters can be managed in the context of a "variant" study. """ + client.headers = {"Authorization": f"Bearer {user_access_token}"} # Create an area area_name = "France" - res = client.post( - f"/v1/studies/{variant_id}/areas", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"name": area_name, "type": "AREA"}, - ) + res = client.post(f"/v1/studies/{variant_id}/areas", json={"name": area_name, "type": "AREA"}) assert res.status_code in {200, 201}, res.json() area_cfg = res.json() area_id = area_cfg["id"] @@ -540,7 +548,6 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var cluster_name = "Th1" res = client.post( f"/v1/studies/{variant_id}/areas/{area_id}/clusters/renewable", - headers={"Authorization": f"Bearer {user_access_token}"}, json={ "name": cluster_name, "group": "Wind Offshore", @@ -553,9 +560,7 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var # Update the renewable cluster res = client.patch( - f"/v1/studies/{variant_id}/areas/{area_id}/clusters/renewable/{cluster_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"unitCount": 15}, + f"/v1/studies/{variant_id}/areas/{area_id}/clusters/renewable/{cluster_id}", json={"unitCount": 15} ) assert res.status_code == 200, res.json() cluster_cfg = res.json() @@ -565,19 +570,13 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var matrix = np.random.randint(0, 2, size=(8760, 1)).tolist() matrix_path = f"input/renewables/series/{area_id}/{cluster_id.lower()}/series" args = {"target": matrix_path, "matrix": matrix} - res = client.post( - f"/v1/studies/{variant_id}/commands", - json=[{"action": "replace_matrix", "args": args}], - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.post(f"/v1/studies/{variant_id}/commands", json=[{"action": "replace_matrix", "args": args}]) assert res.status_code in {200, 201}, res.json() # Duplicate the renewable cluster new_name = "Th2" res = client.post( - f"/v1/studies/{variant_id}/areas/{area_id}/renewables/{cluster_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - params={"newName": new_name}, + f"/v1/studies/{variant_id}/areas/{area_id}/renewables/{cluster_id}", params={"newName": new_name} ) assert res.status_code in {200, 201}, res.json() cluster_cfg = res.json() @@ -585,10 +584,7 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var new_id = cluster_cfg["id"] # Check that the duplicate has the right properties - res = client.get( - f"/v1/studies/{variant_id}/areas/{area_id}/clusters/renewable/{new_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/areas/{area_id}/clusters/renewable/{new_id}") assert res.status_code == 200, res.json() cluster_cfg = res.json() assert cluster_cfg["group"] == "Wind Offshore" @@ -597,27 +593,19 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var # Check that the duplicate has the right matrix new_cluster_matrix_path = f"input/renewables/series/{area_id}/{new_id.lower()}/series" - res = client.get( - f"/v1/studies/{variant_id}/raw", - params={"path": new_cluster_matrix_path}, - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/raw", params={"path": new_cluster_matrix_path}) assert res.status_code == 200 assert res.json()["data"] == matrix # Delete the renewable cluster - res = client.delete( - f"/v1/studies/{variant_id}/areas/{area_id}/clusters/renewable", - headers={"Authorization": f"Bearer {user_access_token}"}, - json=[cluster_id], + # usage of request instead of delete as httpx doesn't support delete with a payload anymore. + res = client.request( + method="DELETE", url=f"/v1/studies/{variant_id}/areas/{area_id}/clusters/renewable", json=[cluster_id] ) assert res.status_code == 204, res.json() # Check the list of variant commands - res = client.get( - f"/v1/studies/{variant_id}/commands", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/commands") assert res.status_code == 200, res.json() commands = res.json() assert len(commands) == 7 diff --git a/tests/integration/study_data_blueprint/test_st_storage.py b/tests/integration/study_data_blueprint/test_st_storage.py index 68fe46b138..8d83d12f37 100644 --- a/tests/integration/study_data_blueprint/test_st_storage.py +++ b/tests/integration/study_data_blueprint/test_st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import re import typing as t @@ -19,11 +31,11 @@ _ST_STORAGE_OUTPUT_860 = create_storage_output(860, cluster_id="dummy", config={"name": "dummy"}) _ST_STORAGE_OUTPUT_880 = create_storage_output(880, cluster_id="dummy", config={"name": "dummy"}) -DEFAULT_CONFIG_860 = json.loads(_ST_STORAGE_860_CONFIG.json(by_alias=True, exclude={"id", "name"})) -DEFAULT_CONFIG_880 = json.loads(_ST_STORAGE_880_CONFIG.json(by_alias=True, exclude={"id", "name"})) +DEFAULT_CONFIG_860 = _ST_STORAGE_860_CONFIG.model_dump(mode="json", by_alias=True, exclude={"id", "name"}) +DEFAULT_CONFIG_880 = _ST_STORAGE_880_CONFIG.model_dump(mode="json", by_alias=True, exclude={"id", "name"}) -DEFAULT_OUTPUT_860 = json.loads(_ST_STORAGE_OUTPUT_860.json(by_alias=True, exclude={"id", "name"})) -DEFAULT_OUTPUT_880 = json.loads(_ST_STORAGE_OUTPUT_880.json(by_alias=True, exclude={"id", "name"})) +DEFAULT_OUTPUT_860 = _ST_STORAGE_OUTPUT_860.model_dump(mode="json", by_alias=True, exclude={"id", "name"}) +DEFAULT_OUTPUT_880 = _ST_STORAGE_OUTPUT_880.model_dump(mode="json", by_alias=True, exclude={"id", "name"}) # noinspection SpellCheckingInspection @@ -313,7 +325,7 @@ def test_lifecycle__nominal( json=[siemens_battery_id], ) assert res.status_code == 204, res.json() - assert res.text in {"", "null"} # Old FastAPI versions return 'null'. + assert not res.text # If the short-term storage list is empty, the deletion should be a no-op. res = client.request( @@ -323,7 +335,7 @@ def test_lifecycle__nominal( json=[], ) assert res.status_code == 204, res.json() - assert res.text in {"", "null"} # Old FastAPI versions return 'null'. + assert not res.text # It's possible to delete multiple short-term storages at once. # In the following example, we will create two short-term storages: @@ -383,7 +395,7 @@ def test_lifecycle__nominal( json=[grand_maison_id, duplicated_output["id"]], ) assert res.status_code == 204, res.json() - assert res.text in {"", "null"} # Old FastAPI versions return 'null'. + assert not res.text # Only one st-storage should remain. res = client.get( @@ -475,7 +487,7 @@ def test_lifecycle__nominal( assert res.status_code == 422, res.json() obj = res.json() description = obj["description"] - assert re.search(r"not a valid enumeration member", description, flags=re.IGNORECASE) + assert re.search(r"Input should be", description) # Check PATCH with the wrong `area_id` res = client.patch( @@ -577,40 +589,26 @@ def test__default_values( Then the short-term storage is created with initialLevel = 0.0, and initialLevelOptim = False. """ # Create a new study in version 860 (or higher) - user_headers = {"Authorization": f"Bearer {user_access_token}"} - res = client.post( - "/v1/studies", - headers=user_headers, - params={"name": "MyStudy", "version": study_version}, - ) + client.headers = {"Authorization": f"Bearer {user_access_token}"} + res = client.post("/v1/studies", params={"name": "MyStudy", "version": study_version}) assert res.status_code in {200, 201}, res.json() study_id = res.json() if study_type == "variant": # Create Variant - res = client.post( - f"/v1/studies/{study_id}/variants", - headers=user_headers, - params={"name": "Variant 1"}, - ) + res = client.post(f"/v1/studies/{study_id}/variants", params={"name": "Variant 1"}) assert res.status_code in {200, 201}, res.json() study_id = res.json() # Create a new area named "FR" - res = client.post( - f"/v1/studies/{study_id}/areas", - headers=user_headers, - json={"name": "FR", "type": "AREA"}, - ) + res = client.post(f"/v1/studies/{study_id}/areas", json={"name": "FR", "type": "AREA"}) assert res.status_code in {200, 201}, res.json() area_id = res.json()["id"] # Create a new short-term storage named "Tesla Battery" tesla_battery = "Tesla Battery" res = client.post( - f"/v1/studies/{study_id}/areas/{area_id}/storages", - headers=user_headers, - json={"name": tesla_battery, "group": "Battery"}, + f"/v1/studies/{study_id}/areas/{area_id}/storages", json={"name": tesla_battery, "group": "Battery"} ) assert res.status_code == 200, res.json() tesla_battery_id = res.json()["id"] @@ -621,7 +619,6 @@ def test__default_values( # are properly set in the configuration file. res = client.get( f"/v1/studies/{study_id}/raw", - headers=user_headers, params={"path": f"input/st-storage/clusters/{area_id}/list/{tesla_battery_id}"}, ) assert res.status_code == 200, res.json() @@ -634,28 +631,19 @@ def test__default_values( # in the variant commands. # Create a variant of the study - res = client.post( - f"/v1/studies/{study_id}/variants", - headers=user_headers, - params={"name": "MyVariant"}, - ) + res = client.post(f"/v1/studies/{study_id}/variants", params={"name": "MyVariant"}) assert res.status_code in {200, 201}, res.json() variant_id = res.json() # Create a new short-term storage named "Siemens Battery" siemens_battery = "Siemens Battery" res = client.post( - f"/v1/studies/{variant_id}/areas/{area_id}/storages", - headers=user_headers, - json={"name": siemens_battery, "group": "Battery"}, + f"/v1/studies/{variant_id}/areas/{area_id}/storages", json={"name": siemens_battery, "group": "Battery"} ) assert res.status_code == 200, res.json() # Check the variant commands - res = client.get( - f"/v1/studies/{variant_id}/commands", - headers=user_headers, - ) + res = client.get(f"/v1/studies/{variant_id}/commands") assert res.status_code == 200, res.json() commands = res.json() assert len(commands) == 1 @@ -679,17 +667,12 @@ def test__default_values( # Update the initialLevel property of the "Siemens Battery" short-term storage to 0.5 siemens_battery_id = transform_name_to_id(siemens_battery) res = client.patch( - f"/v1/studies/{variant_id}/areas/{area_id}/storages/{siemens_battery_id}", - headers=user_headers, - json={"initialLevel": 0.5}, + f"/v1/studies/{variant_id}/areas/{area_id}/storages/{siemens_battery_id}", json={"initialLevel": 0.5} ) assert res.status_code == 200, res.json() # Check the variant commands - res = client.get( - f"/v1/studies/{variant_id}/commands", - headers=user_headers, - ) + res = client.get(f"/v1/studies/{variant_id}/commands") assert res.status_code == 200, res.json() commands = res.json() assert len(commands) == 2 @@ -698,7 +681,7 @@ def test__default_values( "id": ANY, "action": "update_config", "args": { - "data": "0.5", + "data": 0.5, "target": "input/st-storage/clusters/fr/list/siemens battery/initiallevel", }, "version": 1, @@ -708,16 +691,12 @@ def test__default_values( # Update the initialLevel property of the "Siemens Battery" short-term storage back to 0 res = client.patch( f"/v1/studies/{variant_id}/areas/{area_id}/storages/{siemens_battery_id}", - headers=user_headers, json={"initialLevel": 0.0, "injectionNominalCapacity": 1600}, ) assert res.status_code == 200, res.json() # Check the variant commands - res = client.get( - f"/v1/studies/{variant_id}/commands", - headers=user_headers, - ) + res = client.get(f"/v1/studies/{variant_id}/commands") assert res.status_code == 200, res.json() commands = res.json() assert len(commands) == 3 @@ -727,11 +706,11 @@ def test__default_values( "action": "update_config", "args": [ { - "data": "1600.0", + "data": 1600.0, "target": "input/st-storage/clusters/fr/list/siemens battery/injectionnominalcapacity", }, { - "data": "0.0", + "data": 0.0, "target": "input/st-storage/clusters/fr/list/siemens battery/initiallevel", }, ], @@ -743,7 +722,6 @@ def test__default_values( # are properly set in the configuration file. res = client.get( f"/v1/studies/{variant_id}/raw", - headers=user_headers, params={"path": f"input/st-storage/clusters/{area_id}/list/{siemens_battery_id}"}, ) assert res.status_code == 200, res.json() @@ -791,13 +769,10 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var In this test, we want to check that short-term storages can be managed in the context of a "variant" study. """ + client.headers = {"Authorization": f"Bearer {user_access_token}"} # Create an area area_name = "France" - res = client.post( - f"/v1/studies/{variant_id}/areas", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"name": area_name, "type": "AREA"}, - ) + res = client.post(f"/v1/studies/{variant_id}/areas", json={"name": area_name, "type": "AREA"}) assert res.status_code in {200, 201}, res.json() area_cfg = res.json() area_id = area_cfg["id"] @@ -806,7 +781,6 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var cluster_name = "Tesla1" res = client.post( f"/v1/studies/{variant_id}/areas/{area_id}/storages", - headers={"Authorization": f"Bearer {user_access_token}"}, json={ "name": cluster_name, "group": "Battery", @@ -820,9 +794,7 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var # Update the short-term storage res = client.patch( - f"/v1/studies/{variant_id}/areas/{area_id}/storages/{cluster_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"reservoirCapacity": 5600}, + f"/v1/studies/{variant_id}/areas/{area_id}/storages/{cluster_id}", json={"reservoirCapacity": 5600} ) assert res.status_code == 200, res.json() cluster_cfg = res.json() @@ -832,19 +804,13 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var matrix = np.random.randint(0, 2, size=(8760, 1)).tolist() matrix_path = f"input/st-storage/series/{area_id}/{cluster_id.lower()}/pmax_injection" args = {"target": matrix_path, "matrix": matrix} - res = client.post( - f"/v1/studies/{variant_id}/commands", - json=[{"action": "replace_matrix", "args": args}], - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.post(f"/v1/studies/{variant_id}/commands", json=[{"action": "replace_matrix", "args": args}]) assert res.status_code in {200, 201}, res.json() # Duplicate the short-term storage new_name = "Tesla2" res = client.post( - f"/v1/studies/{variant_id}/areas/{area_id}/storages/{cluster_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - params={"newName": new_name}, + f"/v1/studies/{variant_id}/areas/{area_id}/storages/{cluster_id}", params={"newName": new_name} ) assert res.status_code in {200, 201}, res.json() cluster_cfg = res.json() @@ -852,10 +818,7 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var new_id = cluster_cfg["id"] # Check that the duplicate has the right properties - res = client.get( - f"/v1/studies/{variant_id}/areas/{area_id}/storages/{new_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/areas/{area_id}/storages/{new_id}") assert res.status_code == 200, res.json() cluster_cfg = res.json() assert cluster_cfg["group"] == "Battery" @@ -865,27 +828,19 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var # Check that the duplicate has the right matrix new_cluster_matrix_path = f"input/st-storage/series/{area_id}/{new_id.lower()}/pmax_injection" - res = client.get( - f"/v1/studies/{variant_id}/raw", - params={"path": new_cluster_matrix_path}, - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/raw", params={"path": new_cluster_matrix_path}) assert res.status_code == 200 assert res.json()["data"] == matrix # Delete the short-term storage - res = client.delete( - f"/v1/studies/{variant_id}/areas/{area_id}/storages", - headers={"Authorization": f"Bearer {user_access_token}"}, - json=[cluster_id], + # usage of request instead of delete as httpx doesn't support delete with a payload anymore. + res = client.request( + method="DELETE", url=f"/v1/studies/{variant_id}/areas/{area_id}/storages", json=[cluster_id] ) assert res.status_code == 204, res.json() # Check the list of variant commands - res = client.get( - f"/v1/studies/{variant_id}/commands", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/commands") assert res.status_code == 200, res.json() commands = res.json() assert len(commands) == 7 diff --git a/tests/integration/study_data_blueprint/test_table_mode.py b/tests/integration/study_data_blueprint/test_table_mode.py index 2e36b55490..98d7f03393 100644 --- a/tests/integration/study_data_blueprint/test_table_mode.py +++ b/tests/integration/study_data_blueprint/test_table_mode.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import copy import typing as t diff --git a/tests/integration/study_data_blueprint/test_thermal.py b/tests/integration/study_data_blueprint/test_thermal.py index 33e9aef03d..6567fc205f 100644 --- a/tests/integration/study_data_blueprint/test_thermal.py +++ b/tests/integration/study_data_blueprint/test_thermal.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ ## End-to-end test of the thermal cluster management. @@ -28,7 +40,6 @@ * validate the consistency of the matrices (and properties) """ import io -import json import re import typing as t @@ -42,7 +53,7 @@ from antarest.study.storage.rawstudy.model.filesystem.config.thermal import ThermalProperties from tests.integration.utils import wait_task_completion -DEFAULT_PROPERTIES = json.loads(ThermalProperties(name="Dummy").json()) +DEFAULT_PROPERTIES = ThermalProperties(name="Dummy").model_dump(mode="json") DEFAULT_PROPERTIES = {to_camel_case(k): v for k, v in DEFAULT_PROPERTIES.items() if k != "name"} # noinspection SpellCheckingInspection @@ -499,7 +510,6 @@ def test_lifecycle( json={"nox": 10.0}, ) assert res.status_code == 200 - assert res.json()["nox"] == 10.0 # Update with the field `efficiency`. Should succeed even with versions prior to v8.7 res = client.patch( @@ -508,7 +518,6 @@ def test_lifecycle( json={"efficiency": 97.0}, ) assert res.status_code == 200 - assert res.json()["efficiency"] == 97.0 # ============================= # THERMAL CLUSTER DUPLICATION @@ -937,13 +946,10 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var In this test, we want to check that thermal clusters can be managed in the context of a "variant" study. """ + client.headers = {"Authorization": f"Bearer {user_access_token}"} # Create an area area_name = "France" - res = client.post( - f"/v1/studies/{variant_id}/areas", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={"name": area_name, "type": "AREA"}, - ) + res = client.post(f"/v1/studies/{variant_id}/areas", json={"name": area_name, "type": "AREA"}) assert res.status_code in {200, 201}, res.json() area_cfg = res.json() area_id = area_cfg["id"] @@ -952,7 +958,6 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var cluster_name = "Th1" res = client.post( f"/v1/studies/{variant_id}/areas/{area_id}/clusters/thermal", - headers={"Authorization": f"Bearer {user_access_token}"}, json={ "name": cluster_name, "group": "Nuclear", @@ -966,11 +971,7 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var # Update the thermal cluster res = client.patch( - f"/v1/studies/{variant_id}/areas/{area_id}/clusters/thermal/{cluster_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - json={ - "marginalCost": 0.2, - }, + f"/v1/studies/{variant_id}/areas/{area_id}/clusters/thermal/{cluster_id}", json={"marginalCost": 0.2} ) assert res.status_code == 200, res.json() cluster_cfg = res.json() @@ -980,19 +981,13 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var matrix = np.random.randint(0, 2, size=(8760, 1)).tolist() matrix_path = f"input/thermal/prepro/{area_id}/{cluster_id.lower()}/data" args = {"target": matrix_path, "matrix": matrix} - res = client.post( - f"/v1/studies/{variant_id}/commands", - json=[{"action": "replace_matrix", "args": args}], - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.post(f"/v1/studies/{variant_id}/commands", json=[{"action": "replace_matrix", "args": args}]) assert res.status_code in {200, 201}, res.json() # Duplicate the thermal cluster new_name = "Th2" res = client.post( - f"/v1/studies/{variant_id}/areas/{area_id}/thermals/{cluster_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - params={"newName": new_name}, + f"/v1/studies/{variant_id}/areas/{area_id}/thermals/{cluster_id}", params={"newName": new_name} ) assert res.status_code in {200, 201}, res.json() cluster_cfg = res.json() @@ -1000,10 +995,7 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var new_id = cluster_cfg["id"] # Check that the duplicate has the right properties - res = client.get( - f"/v1/studies/{variant_id}/areas/{area_id}/clusters/thermal/{new_id}", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/areas/{area_id}/clusters/thermal/{new_id}") assert res.status_code == 200, res.json() cluster_cfg = res.json() assert cluster_cfg["group"] == "Nuclear" @@ -1013,27 +1005,19 @@ def test_variant_lifecycle(self, client: TestClient, user_access_token: str, var # Check that the duplicate has the right matrix new_cluster_matrix_path = f"input/thermal/prepro/{area_id}/{new_id.lower()}/data" - res = client.get( - f"/v1/studies/{variant_id}/raw", - params={"path": new_cluster_matrix_path}, - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/raw", params={"path": new_cluster_matrix_path}) assert res.status_code == 200 assert res.json()["data"] == matrix # Delete the thermal cluster - res = client.delete( - f"/v1/studies/{variant_id}/areas/{area_id}/clusters/thermal", - headers={"Authorization": f"Bearer {user_access_token}"}, - json=[cluster_id], + # usage of request instead of delete as httpx doesn't support delete with a payload anymore. + res = client.request( + method="DELETE", url=f"/v1/studies/{variant_id}/areas/{area_id}/clusters/thermal", json=[cluster_id] ) assert res.status_code == 204, res.json() # Check the list of variant commands - res = client.get( - f"/v1/studies/{variant_id}/commands", - headers={"Authorization": f"Bearer {user_access_token}"}, - ) + res = client.get(f"/v1/studies/{variant_id}/commands") assert res.status_code == 200, res.json() commands = res.json() assert len(commands) == 7 @@ -1170,9 +1154,9 @@ def test_thermal_cluster_deletion(self, client: TestClient, user_access_token: s assert res.status_code == 200, res.json() # check that deleting the thermal cluster in area_1 fails - res = client.delete( - f"/v1/studies/{internal_study_id}/areas/area_1/clusters/thermal", - json=["cluster_1"], + # usage of request instead of delete as httpx doesn't support delete with a payload anymore. + res = client.request( + method="DELETE", url=f"/v1/studies/{internal_study_id}/areas/area_1/clusters/thermal", json=["cluster_1"] ) assert res.status_code == 403, res.json() @@ -1183,16 +1167,14 @@ def test_thermal_cluster_deletion(self, client: TestClient, user_access_token: s assert res.status_code == 200, res.json() # check that deleting the thermal cluster in area_1 succeeds - res = client.delete( - f"/v1/studies/{internal_study_id}/areas/area_1/clusters/thermal", - json=["cluster_1"], + res = client.request( + method="DELETE", url=f"/v1/studies/{internal_study_id}/areas/area_1/clusters/thermal", json=["cluster_1"] ) assert res.status_code == 204, res.json() # check that deleting the thermal cluster in area_2 fails - res = client.delete( - f"/v1/studies/{internal_study_id}/areas/area_2/clusters/thermal", - json=["cluster_2"], + res = client.request( + method="DELETE", url=f"/v1/studies/{internal_study_id}/areas/area_2/clusters/thermal", json=["cluster_2"] ) assert res.status_code == 403, res.json() @@ -1203,15 +1185,13 @@ def test_thermal_cluster_deletion(self, client: TestClient, user_access_token: s assert res.status_code == 200, res.json() # check that deleting the thermal cluster in area_2 succeeds - res = client.delete( - f"/v1/studies/{internal_study_id}/areas/area_2/clusters/thermal", - json=["cluster_2"], + res = client.request( + method="DELETE", url=f"/v1/studies/{internal_study_id}/areas/area_2/clusters/thermal", json=["cluster_2"] ) assert res.status_code == 204, res.json() # check that deleting the thermal cluster in area_3 succeeds - res = client.delete( - f"/v1/studies/{internal_study_id}/areas/area_3/clusters/thermal", - json=["cluster_3"], + res = client.request( + method="DELETE", url=f"/v1/studies/{internal_study_id}/areas/area_3/clusters/thermal", json=["cluster_3"] ) assert res.status_code == 204, res.json() diff --git a/tests/integration/test_apidoc.py b/tests/integration/test_apidoc.py index 562f7ccb8e..d0eb7445d8 100644 --- a/tests/integration/test_apidoc.py +++ b/tests/integration/test_apidoc.py @@ -1,11 +1,24 @@ -from fastapi.openapi.utils import get_flat_models_from_routes -from fastapi.utils import get_model_definitions -from pydantic.schema import get_model_name_map +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from starlette.testclient import TestClient +from antarest import __version__ + def test_apidoc(client: TestClient) -> None: - # Asserts that the apidoc can be loaded - flat_models = get_flat_models_from_routes(client.app.routes) - model_name_map = get_model_name_map(flat_models) - get_model_definitions(flat_models=flat_models, model_name_map=model_name_map) + # Local import to avoid breaking all tests if FastAPI changes its API + from fastapi.openapi.utils import get_openapi + + routes = client.app.routes + openapi = get_openapi(title="Antares Web", version=__version__, routes=routes) + assert openapi diff --git a/tests/integration/test_core_blueprint.py b/tests/integration/test_core_blueprint.py index 61a0fcbe3a..a60ba6dcfb 100644 --- a/tests/integration/test_core_blueprint.py +++ b/tests/integration/test_core_blueprint.py @@ -1,4 +1,15 @@ -import http +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re from unittest import mock @@ -36,23 +47,3 @@ def test_version_info(self, app: FastAPI): "dependencies": mock.ANY, } assert actual == expected - - -class TestKillWorker: - def test_kill_worker__not_granted(self, app: FastAPI): - client = TestClient(app, raise_server_exceptions=False) - res = client.get("/kill") - assert res.status_code == http.HTTPStatus.UNAUTHORIZED, res.json() - assert res.json() == {"detail": "Missing cookie access_token_cookie"} - - def test_kill_worker__nominal_case(self, app: FastAPI): - client = TestClient(app, raise_server_exceptions=False) - # login as "admin" - res = client.post("/v1/login", json={"username": "admin", "password": "admin"}) - res.raise_for_status() - credentials = res.json() - admin_access_token = credentials["access_token"] - # kill the worker - res = client.get("/kill", headers={"Authorization": f"Bearer {admin_access_token}"}) - assert res.status_code == 500, res.json() - assert not res.content diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index 2119f96658..42b8cb2407 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import os from http import HTTPStatus @@ -97,28 +109,6 @@ def test_main(client: TestClient, admin_access_token: str) -> None: ) assert res.status_code == 200, res.json() - # playlist - res = client.post( - f"/v1/studies/{study_id}/raw?path=settings/generaldata/general/nbyears", - headers={"Authorization": f'Bearer {george_credentials["access_token"]}'}, - json=5, - ) - assert res.status_code == 204 - - res = client.put( - f"/v1/studies/{study_id}/config/playlist", - headers={"Authorization": f'Bearer {george_credentials["access_token"]}'}, - json={"playlist": [1, 2], "weights": {1: 8.0, 3: 9.0}}, - ) - assert res.status_code == 200 - - res = client.get( - f"/v1/studies/{study_id}/config/playlist", - headers={"Authorization": f'Bearer {george_credentials["access_token"]}'}, - ) - assert res.status_code == 200 - assert res.json() == {"1": 8.0, "2": 1.0} - # Update the active ruleset active_ruleset_name = "ruleset test" res = client.post( @@ -440,7 +430,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: }, ) - client.post( + res = client.post( f"/v1/studies/{study_id}/commands", json=[ { @@ -453,6 +443,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: } ], ) + res.raise_for_status() client.post( f"/v1/studies/{study_id}/commands", @@ -462,7 +453,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: "args": { "area_id": "area 2", "cluster_name": "cluster 2", - "parameters": {}, + "parameters": {"nominalcapacity": 2.5}, }, } ], @@ -575,7 +566,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: "min-stable-power": None, "min-up-time": None, "name": "cluster 2", - "nominalcapacity": 0, + "nominalcapacity": 2.5, "spinning": None, "spread-cost": None, "type": None, @@ -594,13 +585,14 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: }, ] - client.post( + res = client.post( f"/v1/studies/{study_id}/links", json={ "area1": "area 1", "area2": "area 2", }, ) + res.raise_for_status() res_links = client.get(f"/v1/studies/{study_id}/links?with_ui=true") assert res_links.json() == [ { @@ -613,15 +605,16 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: # -- `layers` integration tests res = client.get(f"/v1/studies/{study_id}/layers") - assert res.json() == [LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).dict()] + res.raise_for_status() + assert res.json() == [LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).model_dump()] res = client.post(f"/v1/studies/{study_id}/layers?name=test") assert res.json() == "1" res = client.get(f"/v1/studies/{study_id}/layers") assert res.json() == [ - LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).dict(), - LayerInfoDTO(id="1", name="test", areas=[]).dict(), + LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).model_dump(), + LayerInfoDTO(id="1", name="test", areas=[]).model_dump(), ] res = client.put(f"/v1/studies/{study_id}/layers/1?name=test2") @@ -632,8 +625,8 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: assert res.status_code in {200, 201}, res.json() res = client.get(f"/v1/studies/{study_id}/layers") assert res.json() == [ - LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).dict(), - LayerInfoDTO(id="1", name="test2", areas=["area 2"]).dict(), + LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).model_dump(), + LayerInfoDTO(id="1", name="test2", areas=["area 2"]).model_dump(), ] # Delete the layer '1' that has 1 area @@ -643,7 +636,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: # Ensure the layer is deleted res = client.get(f"/v1/studies/{study_id}/layers") assert res.json() == [ - LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).dict(), + LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).model_dump(), ] # Create the layer again without areas @@ -657,7 +650,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: # Ensure the layer is deleted res = client.get(f"/v1/studies/{study_id}/layers") assert res.json() == [ - LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).dict(), + LayerInfoDTO(id="0", name="All", areas=["area 1", "area 2"]).model_dump(), ] # Try to delete a non-existing layer @@ -743,7 +736,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: "simplexOptimizationRange": SimplexOptimizationRange.WEEK.value, } - client.put( + res = client.put( f"/v1/studies/{study_id}/config/optimization/form", json={ "strategicReserve": False, @@ -751,6 +744,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: "simplexOptimizationRange": SimplexOptimizationRange.DAY.value, }, ) + res.raise_for_status() res_optimization_config = client.get(f"/v1/studies/{study_id}/config/optimization/form") res_optimization_config_json = res_optimization_config.json() assert res_optimization_config_json == { @@ -813,7 +807,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: ) assert res.status_code == 422 assert res.json()["exception"] == "RequestValidationError" - assert res.json()["description"] == "value is not a valid integer" + assert res.json()["description"] == "Input should be a valid integer" # General form @@ -1257,7 +1251,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: }, "ntc": {"stochasticTsStatus": False, "intraModal": False}, } - res_ts_config = client.put( + client.put( f"/v1/studies/{study_id}/config/timeseries/form", json={ "thermal": {"stochasticTsStatus": True}, @@ -1472,7 +1466,7 @@ def test_area_management(client: TestClient, admin_access_token: str) -> None: "min-stable-power": None, "min-up-time": None, "name": "cluster 2", - "nominalcapacity": 0, + "nominalcapacity": 2.5, "spinning": None, "spread-cost": None, "type": None, diff --git a/tests/integration/test_integration_token_end_to_end.py b/tests/integration/test_integration_token_end_to_end.py index 66957d1a1e..6bfefe0d3b 100644 --- a/tests/integration/test_integration_token_end_to_end.py +++ b/tests/integration/test_integration_token_end_to_end.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import typing as t from unittest.mock import ANY diff --git a/tests/integration/test_integration_variantmanager_tool.py b/tests/integration/test_integration_variantmanager_tool.py index 4b27c84848..85783fe789 100644 --- a/tests/integration/test_integration_variantmanager_tool.py +++ b/tests/integration/test_integration_variantmanager_tool.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import urllib.parse from pathlib import Path @@ -16,10 +28,12 @@ COMMAND_FILE, MATRIX_STORE_DIR, RemoteVariantGenerator, + create_http_client, extract_commands, generate_diff, generate_study, parse_commands, + set_auth_token, ) from tests.integration.assets import ASSETS_DIR @@ -50,7 +64,9 @@ def generate_study_with_server( ) assert res.status_code == 200, res.json() variant_id = res.json() - generator = RemoteVariantGenerator(variant_id, session=client, token=admin_credentials["access_token"]) + + set_auth_token(client, admin_credentials["access_token"]) + generator = RemoteVariantGenerator(variant_id, host="", session=client) return generator.apply_commands(commands, matrices_dir), variant_id diff --git a/tests/integration/test_integration_watcher.py b/tests/integration/test_integration_watcher.py index e151a3ade3..da28eb76c4 100644 --- a/tests/integration/test_integration_watcher.py +++ b/tests/integration/test_integration_watcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from fastapi import FastAPI from starlette.testclient import TestClient diff --git a/tests/integration/test_studies_upgrade.py b/tests/integration/test_studies_upgrade.py index 9640fb5cf9..37b5058ff2 100644 --- a/tests/integration/test_studies_upgrade.py +++ b/tests/integration/test_studies_upgrade.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os import pytest diff --git a/tests/integration/utils.py b/tests/integration/utils.py index 7781fe0a8a..fa5a34f286 100644 --- a/tests/integration/utils.py +++ b/tests/integration/utils.py @@ -1,4 +1,17 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib +import os import time from typing import Callable @@ -17,24 +30,32 @@ def wait_for(predicate: Callable[[], bool], timeout: float = 10, sleep_time: flo raise TimeoutError(f"task is still in progress after {timeout} seconds") +IS_WINDOWS = os.name == "nt" +TIMEOUT_MULTIPLIER = 2 if IS_WINDOWS else 1 + + def wait_task_completion( client: TestClient, access_token: str, task_id: str, *, - timeout: float = 10, + base_timeout: float = 10, ) -> TaskDTO: - end_time = time.time() + timeout - while time.time() < end_time: - time.sleep(0.1) - res = client.request( - "GET", - f"/v1/tasks/{task_id}", - headers={"Authorization": f"Bearer {access_token}"}, - json={"wait_for_completion": True}, - ) - assert res.status_code == 200 + """ + base_timeout is multiplied by 2 on windows to cope with slow CI + """ + timeout = TIMEOUT_MULTIPLIER * base_timeout + params = {"wait_for_completion": True, "timeout": timeout} + res = client.request( + "GET", + f"/v1/tasks/{task_id}", + headers={"Authorization": f"Bearer {access_token}"}, + params=params, + ) + if res.status_code == 200: task = TaskDTO(**res.json()) if task.status not in {TaskStatus.PENDING, TaskStatus.RUNNING}: return task - raise TimeoutError(f"{timeout} seconds") + elif res.status_code == 408: + raise TimeoutError(f"{timeout} seconds") + raise ValueError(f"Unexpected status code {res.status_code}") diff --git a/tests/integration/variant_blueprint/__init__.py b/tests/integration/variant_blueprint/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/variant_blueprint/__init__.py +++ b/tests/integration/variant_blueprint/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/variant_blueprint/test_renewable_cluster.py b/tests/integration/variant_blueprint/test_renewable_cluster.py index e518244ff9..18e6af0c56 100644 --- a/tests/integration/variant_blueprint/test_renewable_cluster.py +++ b/tests/integration/variant_blueprint/test_renewable_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http import numpy as np diff --git a/tests/integration/variant_blueprint/test_st_storage.py b/tests/integration/variant_blueprint/test_st_storage.py index c28af6790d..b4092f0acb 100644 --- a/tests/integration/variant_blueprint/test_st_storage.py +++ b/tests/integration/variant_blueprint/test_st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http from unittest.mock import ANY @@ -221,18 +233,5 @@ def test_lifecycle( ) assert res.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY description = res.json()["description"] - """ - 4 validation errors for CreateSTStorage - parameters -> group - value is not a valid enumeration member […] - parameters -> injectionnominalcapacity - ensure this value is greater than or equal to 0 (type=value_error.number.not_ge; limit_value=0) - parameters -> initialleveloptim - value could not be parsed to a boolean (type=type_error.bool) - pmax_withdrawal - Matrix values should be between 0 and 1 (type=value_error) - """ - assert "parameters -> group" in description - assert "parameters -> injectionnominalcapacity" in description - assert "parameters -> initialleveloptim" in description - assert "pmax_withdrawal" in description + assert "Matrix values should be between 0 and 1" in description + assert "1 validation error for CreateSTStorage" in description diff --git a/tests/integration/variant_blueprint/test_thermal_cluster.py b/tests/integration/variant_blueprint/test_thermal_cluster.py index 245fd8a02a..db78599cee 100644 --- a/tests/integration/variant_blueprint/test_thermal_cluster.py +++ b/tests/integration/variant_blueprint/test_thermal_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http import random import typing as t @@ -128,7 +140,7 @@ def test_cascade_update( ) assert res.status_code == http.HTTPStatus.OK, res.json() task = TaskDTO(**res.json()) - assert task.dict() == { + assert task.model_dump() == { "completion_date_utc": mock.ANY, "creation_date_utc": mock.ANY, "id": task_id, diff --git a/tests/integration/variant_blueprint/test_variant_manager.py b/tests/integration/variant_blueprint/test_variant_manager.py index 82fa7ab95c..00c75e515c 100644 --- a/tests/integration/variant_blueprint/test_variant_manager.py +++ b/tests/integration/variant_blueprint/test_variant_manager.py @@ -1,13 +1,28 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +import datetime import io import logging import time import typing as t +from pathlib import Path import pytest from starlette.testclient import TestClient from antarest.core.tasks.model import TaskDTO, TaskStatus from tests.integration.assets import ASSETS_DIR +from tests.integration.utils import wait_task_completion @pytest.fixture(name="base_study_id") @@ -33,6 +48,68 @@ def variant_id_fixture( return t.cast(str, res.json()) +@pytest.fixture(name="generate_snapshots") +def generate_snapshot_fixture( + client: TestClient, + admin_access_token: str, + base_study_id: str, + monkeypatch: pytest.MonkeyPatch, + caplog: t.Any, +) -> t.List[str]: + """Generate some snapshots with different date of update and last access""" + + class FakeDatetime: + """ + Class that handle fake timestamp creation/update of variant + """ + + fake_time: datetime.datetime + + @classmethod + def now(cls) -> datetime.datetime: + """Method used to get the custom timestamp""" + return cls.fake_time + + @classmethod + def utcnow(cls) -> datetime.datetime: + """Method used while a variant is created""" + return cls.now() + + # Initialize variant_ids list + variant_ids = [] + + admin_headers = {"Authorization": f"Bearer {admin_access_token}"} + + with caplog.at_level(level=logging.WARNING): + # Generate three different timestamp + older_time = datetime.datetime.utcnow() - datetime.timedelta( + hours=25 + ) # older than the default value which is 24 + old_time = datetime.datetime.utcnow() - datetime.timedelta(hours=8) # older than 6 hours + recent_time = datetime.datetime.utcnow() - datetime.timedelta(hours=2) # older than 0 hours + + with monkeypatch.context() as m: + # Patch the datetime import instance of the variant_study_service package to hack + # the `created_at` and `updated_at` fields + # useful when a variant is created + m.setattr("antarest.study.storage.variantstudy.variant_study_service.datetime", FakeDatetime) + # useful when a study is accessed + m.setattr("antarest.study.service.datetime", FakeDatetime) + + for index, different_time in enumerate([older_time, old_time, recent_time]): + FakeDatetime.fake_time = different_time + res = client.post(f"/v1/studies/{base_study_id}/variants?name=variant{index}", headers=admin_headers) + variant_ids.append(res.json()) + + # Generate snapshot for each variant + task_id = client.put(f"/v1/studies/{variant_ids[index]}/generate", headers=admin_headers) + wait_task_completion( + client, admin_access_token, task_id.json() + ) # wait for the filesystem to be updated + client.get(f"v1/studies/{variant_ids[index]}", headers=admin_headers) + return t.cast(t.List[str], variant_ids) + + def test_variant_manager( client: TestClient, admin_access_token: str, @@ -187,7 +264,7 @@ def test_variant_manager( res = client.get(f"/v1/tasks/{res.json()}?wait_for_completion=true", headers=admin_headers) assert res.status_code == 200 - task_result = TaskDTO.parse_obj(res.json()) + task_result = TaskDTO.model_validate(res.json()) assert task_result.status == TaskStatus.COMPLETED assert task_result.result.success # type: ignore @@ -234,7 +311,7 @@ def test_comments(client: TestClient, admin_access_token: str, variant_id: str) # 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()) + task_result = TaskDTO.model_validate(res.json()) assert task_result.status == TaskStatus.COMPLETED assert task_result.result is not None assert task_result.result.success @@ -308,7 +385,7 @@ def test_outputs(client: TestClient, admin_access_token: str, variant_id: str, t # Wait for task completion res = client.get(f"/v1/tasks/{task_id}", headers=admin_headers, params={"wait_for_completion": True}) res.raise_for_status() - task_result = TaskDTO.parse_obj(res.json()) + task_result = TaskDTO.model_validate(res.json()) assert task_result.status == TaskStatus.COMPLETED assert task_result.result is not None assert task_result.result.success @@ -318,3 +395,44 @@ def test_outputs(client: TestClient, admin_access_token: str, variant_id: str, t assert res.status_code == 200, res.json() outputs = res.json() assert len(outputs) == 1 + + +def test_clear_snapshots( + client: TestClient, + admin_access_token: str, + tmp_path: Path, + generate_snapshots: t.List[str], + monkeypatch: pytest.MonkeyPatch, +) -> None: + """ + The `snapshot/` directory must not exist after a call to `clear-snapshot`. + """ + # Set up + admin_headers = {"Authorization": f"Bearer {admin_access_token}"} + + older = Path(tmp_path).joinpath(f"internal_workspace", generate_snapshots[0], "snapshot") + old = Path(tmp_path).joinpath(f"internal_workspace", generate_snapshots[1], "snapshot") + recent = Path(tmp_path).joinpath(f"internal_workspace", generate_snapshots[2], "snapshot") + + # Test + # Check initial data + assert older.exists() and old.exists() and recent.exists() + + # Delete the older snapshot (default retention hours implicitly equals to 24 hours) + # and check if it was successfully deleted + response = client.put(f"v1/studies/variants/clear-snapshots", headers=admin_headers) + task = response.json() + wait_task_completion(client, admin_access_token, task) + assert (not older.exists()) and old.exists() and recent.exists() + + # Delete the old snapshot and check if it was successfully deleted + response = client.put(f"v1/studies/variants/clear-snapshots?hours=6", headers=admin_headers) + task = response.json() + wait_task_completion(client, admin_access_token, task) + assert (not older.exists()) and (not old.exists()) and recent.exists() + + # Delete the recent snapshot and check if it was successfully deleted + response = client.put(f"v1/studies/variants/clear-snapshots?hours=-1", headers=admin_headers) + task = response.json() + wait_task_completion(client, admin_access_token, task) + assert not (older.exists() and old.exists() and recent.exists()) diff --git a/tests/integration/xpansion_studies_blueprint/__init__.py b/tests/integration/xpansion_studies_blueprint/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/integration/xpansion_studies_blueprint/__init__.py +++ b/tests/integration/xpansion_studies_blueprint/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/integration/xpansion_studies_blueprint/test_integration_xpansion.py b/tests/integration/xpansion_studies_blueprint/test_integration_xpansion.py index b3a563a71e..332b532680 100644 --- a/tests/integration/xpansion_studies_blueprint/test_integration_xpansion.py +++ b/tests/integration/xpansion_studies_blueprint/test_integration_xpansion.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import re import typing as t @@ -11,7 +23,6 @@ def _create_area( client: TestClient, - headers: t.Mapping[str, str], study_id: str, area_name: str, *, @@ -19,7 +30,6 @@ def _create_area( ) -> str: res = client.post( f"/v1/studies/{study_id}/areas", - headers=headers, json={"name": area_name, "type": "AREA", "metadata": {"country": country}}, ) assert res.status_code in {200, 201}, res.json() @@ -28,32 +38,28 @@ def _create_area( def _create_link( client: TestClient, - headers: t.Mapping[str, str], study_id: str, src_area_id: str, dst_area_id: str, ) -> None: - res = client.post( - f"/v1/studies/{study_id}/links", - headers=headers, - json={"area1": src_area_id, "area2": dst_area_id}, - ) + res = client.post(f"/v1/studies/{study_id}/links", json={"area1": src_area_id, "area2": dst_area_id}) assert res.status_code in {200, 201}, res.json() def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_token: str) -> None: headers = {"Authorization": f"Bearer {admin_access_token}"} + client.headers = headers - res = client.post("/v1/studies", headers=headers, params={"name": "foo", "version": "860"}) + res = client.post("/v1/studies", params={"name": "foo", "version": "860"}) assert res.status_code == 201, res.json() study_id = res.json() - area1_id = _create_area(client, headers, study_id, "area1", country="FR") - area2_id = _create_area(client, headers, study_id, "area2", country="DE") - area3_id = _create_area(client, headers, study_id, "area3", country="DE") - _create_link(client, headers, study_id, area1_id, area2_id) + area1_id = _create_area(client, study_id, "area1", country="FR") + area2_id = _create_area(client, study_id, "area2", country="DE") + area3_id = _create_area(client, study_id, "area3", country="DE") + _create_link(client, study_id, area1_id, area2_id) - res = client.post(f"/v1/studies/{study_id}/extensions/xpansion", headers=headers) + res = client.post(f"/v1/studies/{study_id}/extensions/xpansion") assert res.status_code in {200, 201}, res.json() expansion_path = tmp_path / "internal_workspace" / study_id / "user" / "expansion" @@ -61,9 +67,9 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t # Create a client for Xpansion with the xpansion URL xpansion_base_url = f"/v1/studies/{study_id}/extensions/xpansion/" - xp_client = TestClient(client.app, base_url=urljoin(client.base_url, xpansion_base_url)) - - res = xp_client.get("settings", headers=headers) + xp_client = TestClient(client.app, base_url=urljoin(str(client.base_url), xpansion_base_url)) + xp_client.headers = headers + res = xp_client.get("settings") assert res.status_code == 200 assert res.json() == { "master": "integer", @@ -82,7 +88,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "sensitivity_config": {"epsilon": 0.0, "projection": [], "capex": False}, } - res = xp_client.put("settings", headers=headers, json={"optimality_gap": 42}) + res = xp_client.put("settings", json={"optimality_gap": 42}) assert res.status_code == 200 assert res.json() == { "master": "integer", @@ -101,13 +107,13 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "sensitivity_config": {"epsilon": 0.0, "projection": [], "capex": False}, } - res = xp_client.put("settings", headers=headers, json={"additional-constraints": "missing.txt"}) + res = xp_client.put("settings", json={"additional-constraints": "missing.txt"}) assert res.status_code == 404 err_obj = res.json() assert re.search(r"file 'missing.txt' does not exist", err_obj["description"]) assert err_obj["exception"] == "XpansionFileNotFoundError" - res = xp_client.put("settings/additional-constraints", headers=headers, params={"filename": "missing.txt"}) + res = xp_client.put("settings/additional-constraints", params={"filename": "missing.txt"}) assert res.status_code == 404 err_obj = res.json() assert re.search(r"file 'missing.txt' does not exist", err_obj["description"]) @@ -127,7 +133,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "image/jpeg", ) } - res = xp_client.post("resources/constraints", headers=headers, files=files) + res = xp_client.post("resources/constraints", files=files) assert res.status_code in {200, 201} actual_path = expansion_path / "constraints" / filename_constraints1 assert actual_path.read_text() == content_constraints1 @@ -140,7 +146,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t ), } - res = xp_client.post("resources/constraints", headers=headers, files=files) + res = xp_client.post("resources/constraints", files=files) assert res.status_code == 409 err_obj = res.json() assert re.search( @@ -157,7 +163,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "image/jpeg", ), } - res = xp_client.post("resources/constraints", headers=headers, files=files) + res = xp_client.post("resources/constraints", files=files) assert res.status_code in {200, 201} files = { @@ -167,14 +173,14 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "image/jpeg", ), } - res = xp_client.post("resources/constraints", headers=headers, files=files) + res = xp_client.post("resources/constraints", files=files) assert res.status_code in {200, 201} - res = xp_client.get(f"resources/constraints/{filename_constraints1}", headers=headers) + res = xp_client.get(f"resources/constraints/{filename_constraints1}") assert res.status_code == 200 assert res.json() == content_constraints1 - res = xp_client.get("resources/constraints/", headers=headers) + res = xp_client.get("resources/constraints/") assert res.status_code == 200 assert res.json() == [ filename_constraints1, @@ -182,14 +188,10 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t filename_constraints3, ] - res = xp_client.put( - "settings/additional-constraints", - headers=headers, - params={"filename": filename_constraints1}, - ) + res = xp_client.put("settings/additional-constraints", params={"filename": filename_constraints1}) assert res.status_code == 200 - res = xp_client.delete(f"resources/constraints/{filename_constraints1}", headers=headers) + res = xp_client.delete(f"resources/constraints/{filename_constraints1}") assert res.status_code == 409 err_obj = res.json() assert re.search( @@ -199,10 +201,10 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t ) assert err_obj["exception"] == "FileCurrentlyUsedInSettings" - res = xp_client.put("settings/additional-constraints", headers=headers) + res = xp_client.put("settings/additional-constraints") assert res.status_code == 200 - res = xp_client.delete(f"resources/constraints/{filename_constraints1}", headers=headers) + res = xp_client.delete(f"resources/constraints/{filename_constraints1}") assert res.status_code == 200 candidate1 = { @@ -211,7 +213,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "annual-cost-per-mw": 1, "max-investment": 1.0, } - res = xp_client.post("candidates", headers=headers, json=candidate1) + res = xp_client.post("candidates", json=candidate1) assert res.status_code in {200, 201} candidate2 = { @@ -220,7 +222,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "annual-cost-per-mw": 1, "max-investment": 1.0, } - res = xp_client.post("candidates", headers=headers, json=candidate2) + res = xp_client.post("candidates", json=candidate2) assert res.status_code == 404 err_obj = res.json() assert re.search( @@ -236,7 +238,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "annual-cost-per-mw": 1, "max-investment": 1.0, } - res = xp_client.post("candidates", headers=headers, json=candidate3) + res = xp_client.post("candidates", json=candidate3) assert res.status_code == 404 err_obj = res.json() assert re.search( @@ -259,12 +261,12 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "txt/csv", ) } - res = xp_client.post("resources/capacities", headers=headers, files=files) + res = xp_client.post("resources/capacities", files=files) assert res.status_code in {200, 201} actual_path = expansion_path / "capa" / filename_capa1 assert actual_path.read_text() == content_capa1 - res = xp_client.post("resources/capacities", headers=headers, files=files) + res = xp_client.post("resources/capacities", files=files) assert res.status_code == 409 err_obj = res.json() assert re.search( @@ -281,7 +283,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "txt/csv", ) } - res = xp_client.post("resources/capacities", headers=headers, files=files) + res = xp_client.post("resources/capacities", files=files) assert res.status_code in {200, 201} files = { @@ -291,11 +293,11 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "txt/csv", ) } - res = xp_client.post("resources/capacities", headers=headers, files=files) + res = xp_client.post("resources/capacities", files=files) assert res.status_code in {200, 201} # get single capa - res = xp_client.get(f"resources/capacities/{filename_capa1}", headers=headers) + res = xp_client.get(f"resources/capacities/{filename_capa1}") assert res.status_code == 200 assert res.json() == { "columns": [0], @@ -303,7 +305,7 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "index": [0], } - res = xp_client.get("resources/capacities", headers=headers) + res = xp_client.get("resources/capacities") assert res.status_code == 200 assert res.json() == [filename_capa1, filename_capa2, filename_capa3] @@ -314,21 +316,21 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "max-investment": 1.0, "link-profile": filename_capa1, } - res = xp_client.post("candidates", headers=headers, json=candidate4) + res = xp_client.post("candidates", json=candidate4) assert res.status_code in {200, 201} - res = xp_client.get(f"candidates/{candidate1['name']}", headers=headers) + res = xp_client.get(f"candidates/{candidate1['name']}") assert res.status_code == 200 - assert res.json() == XpansionCandidateDTO.parse_obj(candidate1).dict(by_alias=True) + assert res.json() == XpansionCandidateDTO.model_validate(candidate1).model_dump(by_alias=True) - res = xp_client.get("candidates", headers=headers) + res = xp_client.get("candidates") assert res.status_code == 200 assert res.json() == [ - XpansionCandidateDTO.parse_obj(candidate1).dict(by_alias=True), - XpansionCandidateDTO.parse_obj(candidate4).dict(by_alias=True), + XpansionCandidateDTO.model_validate(candidate1).model_dump(by_alias=True), + XpansionCandidateDTO.model_validate(candidate4).model_dump(by_alias=True), ] - res = xp_client.delete(f"resources/capacities/{filename_capa1}", headers=headers) + res = xp_client.delete(f"resources/capacities/{filename_capa1}") assert res.status_code == 409 err_obj = res.json() assert re.search( @@ -343,13 +345,13 @@ def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_t "annual-cost-per-mw": 1, "max-investment": 1.0, } - res = xp_client.put(f"candidates/{candidate4['name']}", headers=headers, json=candidate5) + res = xp_client.put(f"candidates/{candidate4['name']}", json=candidate5) assert res.status_code == 200 - res = xp_client.delete(f"resources/capacities/{filename_capa1}", headers=headers) + res = xp_client.delete(f"resources/capacities/{filename_capa1}") assert res.status_code == 200 - res = client.delete(f"/v1/studies/{study_id}/extensions/xpansion", headers=headers) + res = client.delete(f"/v1/studies/{study_id}/extensions/xpansion") assert res.status_code == 200 assert not expansion_path.exists() diff --git a/tests/launcher/__init__.py b/tests/launcher/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/launcher/__init__.py +++ b/tests/launcher/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/launcher/assets/__init__.py b/tests/launcher/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/launcher/assets/__init__.py +++ b/tests/launcher/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/launcher/test_extension_adequacy_patch.py b/tests/launcher/test_extension_adequacy_patch.py index 19b1f256f5..6d8f0f7c9a 100644 --- a/tests/launcher/test_extension_adequacy_patch.py +++ b/tests/launcher/test_extension_adequacy_patch.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/launcher/test_local_launcher.py b/tests/launcher/test_local_launcher.py index 53adc03bf0..0bad3cdd74 100644 --- a/tests/launcher/test_local_launcher.py +++ b/tests/launcher/test_local_launcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os import textwrap import uuid diff --git a/tests/launcher/test_log_manager.py b/tests/launcher/test_log_manager.py index 46bb2f7561..cfc6b87b52 100644 --- a/tests/launcher/test_log_manager.py +++ b/tests/launcher/test_log_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import time from pathlib import Path diff --git a/tests/launcher/test_log_parser.py b/tests/launcher/test_log_parser.py index 1c17177255..d8356319bb 100644 --- a/tests/launcher/test_log_parser.py +++ b/tests/launcher/test_log_parser.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import sys from typing import List, Union diff --git a/tests/launcher/test_model.py b/tests/launcher/test_model.py index fe7ccead1e..36f6bd8948 100644 --- a/tests/launcher/test_model.py +++ b/tests/launcher/test_model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import typing as t import uuid diff --git a/tests/launcher/test_repository.py b/tests/launcher/test_repository.py index 1bee383473..f5bcf2672f 100644 --- a/tests/launcher/test_repository.py +++ b/tests/launcher/test_repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime from unittest.mock import Mock from uuid import uuid4 diff --git a/tests/launcher/test_service.py b/tests/launcher/test_service.py index 6998df5667..0c4904a870 100644 --- a/tests/launcher/test_service.py +++ b/tests/launcher/test_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import math import os @@ -15,7 +27,7 @@ from antarest.core.config import ( Config, - InvalidConfigurationError, + Launcher, LauncherConfig, LocalConfig, NbCoresConfig, @@ -83,7 +95,7 @@ def test_service_run_study(self, get_current_user_mock) -> None: study_id="study_uuid", job_status=JobStatus.PENDING, launcher="local", - launcher_params=LauncherParametersDTO().json(), + launcher_params=LauncherParametersDTO().model_dump_json(), ) repository = Mock() repository.save.return_value = pending @@ -124,12 +136,12 @@ def test_service_run_study(self, get_current_user_mock) -> None: # so we need to compare them manually. mock_call = repository.save.mock_calls[0] actual_obj: JobResult = mock_call.args[0] - assert actual_obj.to_dto().dict() == pending.to_dto().dict() + assert actual_obj.to_dto().model_dump() == pending.to_dto().model_dump() event_bus.push.assert_called_once_with( Event( type=EventType.STUDY_JOB_STARTED, - payload=pending.to_dto().dict(), + payload=pending.to_dto().model_dump(), permissions=PermissionInfo(owner=0), ) ) @@ -480,11 +492,6 @@ def test_service_get_solver_versions( "unknown", {}, id="local-config-unknown", - marks=pytest.mark.xfail( - reason="Configuration is not available for the 'unknown' launcher", - raises=InvalidConfigurationError, - strict=True, - ), ), pytest.param( { @@ -512,11 +519,6 @@ def test_service_get_solver_versions( "unknown", {}, id="slurm-config-unknown", - marks=pytest.mark.xfail( - reason="Configuration is not available for the 'unknown' launcher", - raises=InvalidConfigurationError, - strict=True, - ), ), pytest.param( { @@ -557,10 +559,13 @@ def test_get_nb_cores( ) # Fetch the number of cores - actual = launcher_service.get_nb_cores(solver) - - # Check the result - assert actual == NbCoresConfig(**expected) + try: + actual = launcher_service.get_nb_cores(Launcher(solver)) + except ValueError as e: + assert e.args[0] == f"'{solver}' is not a valid Launcher" + else: + # Check the result + assert actual == NbCoresConfig(**expected) @pytest.mark.unit_test def test_service_kill_job(self, tmp_path: Path) -> None: @@ -884,7 +889,7 @@ def test_save_solver_stats(self, tmp_path: Path) -> None: solver_stats=expected_saved_stats, owner_id=1, ) - assert actual_obj.to_dto().dict() == expected_obj.to_dto().dict() + assert actual_obj.to_dto().model_dump() == expected_obj.to_dto().model_dump() zip_file = tmp_path / "test.zip" with ZipFile(zip_file, "w", ZIP_DEFLATED) as output_data: @@ -901,7 +906,7 @@ def test_save_solver_stats(self, tmp_path: Path) -> None: solver_stats="0\n1", owner_id=1, ) - assert actual_obj.to_dto().dict() == expected_obj.to_dto().dict() + assert actual_obj.to_dto().model_dump() == expected_obj.to_dto().model_dump() @pytest.mark.parametrize( ["running_jobs", "expected_result", "default_launcher"], @@ -984,7 +989,7 @@ def test_get_load( job_repository.get_running.return_value = running_jobs - launcher_expected_result = LauncherLoadDTO.parse_obj(expected_result) + launcher_expected_result = LauncherLoadDTO.model_validate(expected_result) actual_result = launcher_service.get_load() assert launcher_expected_result.launcher_status == actual_result.launcher_status diff --git a/tests/launcher/test_slurm_launcher.py b/tests/launcher/test_slurm_launcher.py index a509342837..4482eee71a 100644 --- a/tests/launcher/test_slurm_launcher.py +++ b/tests/launcher/test_slurm_launcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os import random import textwrap diff --git a/tests/launcher/test_ssh_client.py b/tests/launcher/test_ssh_client.py index 0ced719cde..df0af69fb2 100644 --- a/tests/launcher/test_ssh_client.py +++ b/tests/launcher/test_ssh_client.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import math from unittest.mock import Mock diff --git a/tests/launcher/test_web.py b/tests/launcher/test_web.py index e0800cf019..e1104f87af 100644 --- a/tests/launcher/test_web.py +++ b/tests/launcher/test_web.py @@ -1,5 +1,17 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import http -from typing import Dict, List, Union +from typing import List, Union from unittest.mock import Mock, call from uuid import uuid4 @@ -7,6 +19,7 @@ from fastapi import FastAPI from starlette.testclient import TestClient +from antarest.core.application import create_app_ctxt from antarest.core.config import Config, SecurityConfig from antarest.core.jwt import DEFAULT_ADMIN_USER, JWTGroup, JWTUser from antarest.core.requests import RequestParameters @@ -23,10 +36,9 @@ def create_app(service: Mock) -> FastAPI: - app = FastAPI(title=__name__) - + build_ctxt = create_app_ctxt(FastAPI(title=__name__)) build_launcher( - app, + build_ctxt, study_service=Mock(), file_transfer_manager=Mock(), task_service=Mock(), @@ -34,7 +46,7 @@ def create_app(service: Mock) -> FastAPI: config=Config(security=SecurityConfig(disabled=True)), cache=Mock(), ) - return app + return build_ctxt.build() @pytest.mark.unit_test @@ -74,7 +86,7 @@ def test_result() -> None: res = client.get(f"/v1/launcher/jobs/{job}") assert res.status_code == 200 - assert JobResultDTO.parse_obj(res.json()) == result.to_dto() + assert JobResultDTO.model_validate(res.json()) == result.to_dto() service.get_result.assert_called_once_with(job, RequestParameters(DEFAULT_ADMIN_USER)) @@ -98,11 +110,11 @@ def test_jobs() -> None: client = TestClient(app) res = client.get(f"/v1/launcher/jobs?study={str(study_id)}") assert res.status_code == 200 - assert [JobResultDTO.parse_obj(j) for j in res.json()] == [result.to_dto()] + assert [JobResultDTO.model_validate(j) for j in res.json()] == [result.to_dto()] res = client.get("/v1/launcher/jobs") assert res.status_code == 200 - assert [JobResultDTO.parse_obj(j) for j in res.json()] == [result.to_dto()] + assert [JobResultDTO.model_validate(j) for j in res.json()] == [result.to_dto()] service.get_jobs.assert_has_calls( [ call( @@ -136,7 +148,7 @@ def test_get_solver_versions() -> None: pytest.param( "", http.HTTPStatus.UNPROCESSABLE_ENTITY, - {"detail": "Unknown solver configuration: ''"}, + "Input should be 'slurm', 'local' or 'default'", id="empty", ), pytest.param("default", http.HTTPStatus.OK, ["1", "2", "3"], id="default"), @@ -145,7 +157,7 @@ def test_get_solver_versions() -> None: pytest.param( "remote", http.HTTPStatus.UNPROCESSABLE_ENTITY, - {"detail": "Unknown solver configuration: 'remote'"}, + "Input should be 'slurm', 'local' or 'default'", id="remote", ), ], @@ -153,7 +165,7 @@ def test_get_solver_versions() -> None: def test_get_solver_versions__with_query_string( solver: str, status_code: http.HTTPStatus, - expected: Union[List[str], Dict[str, str]], + expected: Union[List[str], str], ) -> None: service = Mock() if status_code == http.HTTPStatus.OK: @@ -165,7 +177,12 @@ def test_get_solver_versions__with_query_string( client = TestClient(app) res = client.get(f"/v1/launcher/versions?solver={solver}") assert res.status_code == status_code # OK or UNPROCESSABLE_ENTITY - assert res.json() == expected + if status_code == http.HTTPStatus.OK: + assert res.json() == expected + else: + actual = res.json()["detail"][0] + assert actual["type"] == "enum" + assert actual["msg"] == expected @pytest.mark.unit_test diff --git a/tests/login/__init__.py b/tests/login/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/login/__init__.py +++ b/tests/login/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/login/conftest.py b/tests/login/conftest.py index 61bebee728..38c90a9c8d 100644 --- a/tests/login/conftest.py +++ b/tests/login/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import pytest from antarest.core.config import Config diff --git a/tests/login/test_ldap.py b/tests/login/test_ldap.py index bb23cd86c2..aa674f68b4 100644 --- a/tests/login/test_ldap.py +++ b/tests/login/test_ldap.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import threading import typing as t diff --git a/tests/login/test_login_service.py b/tests/login/test_login_service.py index e48a54a918..0c4c9b756c 100644 --- a/tests/login/test_login_service.py +++ b/tests/login/test_login_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t from unittest.mock import patch @@ -370,7 +382,7 @@ def test_get_group_info(self, login_service: LoginService) -> None: actual = login_service.get_group_info("superman", _param) assert actual is not None assert actual.name == "Superman" - assert [obj.dict() for obj in actual.users] == [ + assert [obj.model_dump() for obj in actual.users] == [ {"id": 2, "name": "Clark Kent", "role": RoleType.ADMIN}, {"id": 3, "name": "Lois Lane", "role": RoleType.READER}, ] @@ -450,7 +462,7 @@ def test_get_user_info(self, login_service: LoginService) -> None: clark_id = 2 actual = login_service.get_user_info(clark_id, _param) assert actual is not None - assert actual.dict() == { + assert actual.model_dump() == { "id": clark_id, "name": "Clark Kent", "roles": [ @@ -468,7 +480,7 @@ def test_get_user_info(self, login_service: LoginService) -> None: lois_id = 3 actual = login_service.get_user_info(lois_id, _param) assert actual is not None - assert actual.dict() == { + assert actual.model_dump() == { "id": lois_id, "name": "Lois Lane", "roles": [ @@ -491,7 +503,7 @@ def test_get_user_info(self, login_service: LoginService) -> None: _param = get_user_param(login_service, user_id=lois_id, group_id="superman") actual = login_service.get_user_info(lois_id, _param) assert actual is not None - assert actual.dict() == { + assert actual.model_dump() == { "id": lois_id, "name": "Lois Lane", "roles": [ @@ -512,7 +524,7 @@ def test_get_user_info(self, login_service: LoginService) -> None: _param = get_bot_param(login_service, bot_id=bot.id) actual = login_service.get_user_info(lois_id, _param) assert actual is not None - assert actual.dict() == { + assert actual.model_dump() == { "id": lois_id, "name": "Lois Lane", "roles": [ @@ -566,13 +578,13 @@ def test_get_bot_info(self, login_service: LoginService) -> None: _param = get_user_param(login_service, user_id=ADMIN_ID, group_id="admin") actual = login_service.get_bot_info(joh_bot.id, _param) assert actual is not None - assert actual.dict() == {"id": 6, "isAuthor": True, "name": "Maria", "roles": []} + assert actual.model_dump() == {"id": 6, "isAuthor": True, "name": "Maria", "roles": []} # Joh Fredersen can get its own bot _param = get_user_param(login_service, user_id=joh_id, group_id="superman") actual = login_service.get_bot_info(joh_bot.id, _param) assert actual is not None - assert actual.dict() == {"id": 6, "isAuthor": True, "name": "Maria", "roles": []} + assert actual.model_dump() == {"id": 6, "isAuthor": True, "name": "Maria", "roles": []} # The bot cannot get itself _param = get_bot_param(login_service, bot_id=joh_bot.id) @@ -601,13 +613,13 @@ def test_get_all_bots_by_owner(self, login_service: LoginService) -> None: _param = get_user_param(login_service, user_id=ADMIN_ID, group_id="admin") actual = login_service.get_all_bots_by_owner(joh_id, _param) expected = [{"id": joh_bot.id, "is_author": True, "name": "Maria", "owner": joh_id}] - assert [obj.to_dto().dict() for obj in actual] == expected + assert [obj.to_dto().model_dump() for obj in actual] == expected # Freder Fredersen can get its own bot _param = get_user_param(login_service, user_id=joh_id, group_id="superman") actual = login_service.get_all_bots_by_owner(joh_id, _param) expected = [{"id": joh_bot.id, "is_author": True, "name": "Maria", "owner": joh_id}] - assert [obj.to_dto().dict() for obj in actual] == expected + assert [obj.to_dto().model_dump() for obj in actual] == expected # The bot cannot get itself _param = get_bot_param(login_service, bot_id=joh_bot.id) @@ -718,7 +730,7 @@ def test_get_all_groups(self, login_service: LoginService) -> None: # The site admin can get all groups _param = get_user_param(login_service, user_id=ADMIN_ID, group_id="admin") actual = login_service.get_all_groups(_param) - assert [g.dict() for g in actual] == [ + assert [g.model_dump() for g in actual] == [ {"id": "admin", "name": "X-Men"}, {"id": "superman", "name": "Superman"}, {"id": "metropolis", "name": "Metropolis"}, @@ -727,19 +739,19 @@ def test_get_all_groups(self, login_service: LoginService) -> None: # The group admin can its own groups _param = get_user_param(login_service, user_id=2, group_id="superman") actual = login_service.get_all_groups(_param) - assert [g.dict() for g in actual] == [{"id": "superman", "name": "Superman"}] + assert [g.model_dump() for g in actual] == [{"id": "superman", "name": "Superman"}] # The user can get its own groups _param = get_user_param(login_service, user_id=3, group_id="superman") actual = login_service.get_all_groups(_param) - assert [g.dict() for g in actual] == [{"id": "superman", "name": "Superman"}] + assert [g.model_dump() for g in actual] == [{"id": "superman", "name": "Superman"}] @with_db_context def test_get_all_users(self, login_service: LoginService) -> None: # The site admin can get all users _param = get_user_param(login_service, user_id=ADMIN_ID, group_id="admin") actual = login_service.get_all_users(_param) - assert [u.dict() for u in actual] == [ + assert [u.model_dump() for u in actual] == [ {"id": 1, "name": "Professor Xavier"}, {"id": 2, "name": "Clark Kent"}, {"id": 3, "name": "Lois Lane"}, @@ -751,7 +763,7 @@ def test_get_all_users(self, login_service: LoginService) -> None: # note: I don't know why the group admin can get all users -- Laurent _param = get_user_param(login_service, user_id=2, group_id="superman") actual = login_service.get_all_users(_param) - assert [u.dict() for u in actual] == [ + assert [u.model_dump() for u in actual] == [ {"id": 1, "name": "Professor Xavier"}, {"id": 2, "name": "Clark Kent"}, {"id": 3, "name": "Lois Lane"}, @@ -762,7 +774,7 @@ def test_get_all_users(self, login_service: LoginService) -> None: # The user can get its own users _param = get_user_param(login_service, user_id=3, group_id="superman") actual = login_service.get_all_users(_param) - assert [u.dict() for u in actual] == [ + assert [u.model_dump() for u in actual] == [ {"id": 2, "name": "Clark Kent"}, {"id": 3, "name": "Lois Lane"}, ] @@ -777,7 +789,7 @@ def test_get_all_bots(self, login_service: LoginService) -> None: # The site admin can get all bots _param = get_user_param(login_service, user_id=ADMIN_ID, group_id="admin") actual = login_service.get_all_bots(_param) - assert [b.to_dto().dict() for b in actual] == [ + assert [b.to_dto().model_dump() for b in actual] == [ {"id": joh_bot.id, "is_author": True, "name": "Maria", "owner": joh_id}, ] @@ -796,7 +808,7 @@ def test_get_all_roles_in_group(self, login_service: LoginService) -> None: # The site admin can get all roles in a given group _param = get_user_param(login_service, user_id=ADMIN_ID, group_id="admin") actual = login_service.get_all_roles_in_group("superman", _param) - assert [b.to_dto().dict() for b in actual] == [ + assert [b.to_dto().model_dump() for b in actual] == [ { "group": {"id": "superman", "name": "Superman"}, "identity": {"id": 2, "name": "Clark Kent"}, @@ -812,7 +824,7 @@ def test_get_all_roles_in_group(self, login_service: LoginService) -> None: # The group admin can get all roles his own group _param = get_user_param(login_service, user_id=2, group_id="superman") actual = login_service.get_all_roles_in_group("superman", _param) - assert [b.to_dto().dict() for b in actual] == [ + assert [b.to_dto().model_dump() for b in actual] == [ { "group": {"id": "superman", "name": "Superman"}, "identity": {"id": 2, "name": "Clark Kent"}, diff --git a/tests/login/test_model.py b/tests/login/test_model.py index e1ef0bc928..a37cdb7bd5 100644 --- a/tests/login/test_model.py +++ b/tests/login/test_model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from sqlalchemy.engine.base import Engine # type: ignore from sqlalchemy.orm import sessionmaker # type: ignore @@ -12,7 +24,7 @@ User, init_admin_user, ) -from antarest.utils import SESSION_ARGS +from antarest.service_creator import SESSION_ARGS TEST_ADMIN_PASS_WORD = "test" diff --git a/tests/login/test_repository.py b/tests/login/test_repository.py index 5ab7406dc4..1eed93d437 100644 --- a/tests/login/test_repository.py +++ b/tests/login/test_repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import pytest from sqlalchemy.orm import Session # type: ignore diff --git a/tests/login/test_web.py b/tests/login/test_web.py index 0f7175fc54..389dc94cf7 100644 --- a/tests/login/test_web.py +++ b/tests/login/test_web.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import base64 import json from datetime import timedelta @@ -7,12 +19,13 @@ import pytest from fastapi import FastAPI -from fastapi_jwt_auth import AuthJWT from starlette.testclient import TestClient +from antarest.core.application import AppBuildContext, create_app_ctxt from antarest.core.config import Config, SecurityConfig from antarest.core.jwt import JWTGroup, JWTUser from antarest.core.requests import RequestParameters +from antarest.fastapi_jwt_auth import AuthJWT from antarest.login.main import build_login from antarest.login.model import ( Bot, @@ -51,15 +64,16 @@ def get_config(): authjwt_token_location=("headers", "cookies"), ) + app_ctxt = create_app_ctxt(app) build_login( - app, + app_ctxt, service=service, config=Config( resources_path=Path(), security=SecurityConfig(disabled=auth_disabled), ), ) - return app + return app_ctxt.build() class TokenType: @@ -177,7 +191,7 @@ def test_user() -> None: client = TestClient(app) res = client.get("/v1/users", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == [User(id=1, name="user").to_dto().dict()] + assert res.json() == [User(id=1, name="user").to_dto().model_dump()] @pytest.mark.unit_test @@ -189,7 +203,7 @@ def test_user_id() -> None: client = TestClient(app) res = client.get("/v1/users/1", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == User(id=1, name="user").to_dto().dict() + assert res.json() == User(id=1, name="user").to_dto().model_dump() @pytest.mark.unit_test @@ -201,7 +215,7 @@ def test_user_id_with_details() -> None: client = TestClient(app) res = client.get("/v1/users/1?details=true", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == IdentityDTO(id=1, name="user", roles=[]).dict() + assert res.json() == IdentityDTO(id=1, name="user", roles=[]).model_dump() @pytest.mark.unit_test @@ -216,12 +230,12 @@ def test_user_create() -> None: res = client.post( "/v1/users", headers=create_auth_token(app), - json=user.dict(), + json=user.model_dump(), ) assert res.status_code == 200 service.create_user.assert_called_once_with(user, PARAMS) - assert res.json() == user_id.to_dto().dict() + assert res.json() == user_id.to_dto().model_dump() @pytest.mark.unit_test @@ -232,7 +246,7 @@ def test_user_save() -> None: app = create_app(service) client = TestClient(app) - user_obj = user.to_dto().dict() + user_obj = user.to_dto().model_dump() res = client.put( "/v1/users/0", headers=create_auth_token(app), @@ -244,7 +258,7 @@ def test_user_save() -> None: assert service.save_user.call_count == 1 call = service.save_user.call_args_list[0] - assert call[0][0].to_dto().dict() == user_obj + assert call[0][0].to_dto().model_dump() == user_obj assert call[0][1] == PARAMS @@ -269,7 +283,7 @@ def test_group() -> None: client = TestClient(app) res = client.get("/v1/groups", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == [Group(id="my-group", name="group").to_dto().dict()] + assert res.json() == [Group(id="my-group", name="group").to_dto().model_dump()] @pytest.mark.unit_test @@ -281,7 +295,7 @@ def test_group_id() -> None: client = TestClient(app) res = client.get("/v1/groups/1", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == Group(id="my-group", name="group").to_dto().dict() + assert res.json() == Group(id="my-group", name="group").to_dto().model_dump() @pytest.mark.unit_test @@ -299,7 +313,7 @@ def test_group_create() -> None: ) assert res.status_code == 200 - assert res.json() == group.to_dto().dict() + assert res.json() == group.to_dto().model_dump() @pytest.mark.unit_test @@ -329,7 +343,7 @@ def test_role() -> None: client = TestClient(app) res = client.get("/v1/roles/group/g", headers=create_auth_token(app)) assert res.status_code == 200 - assert [RoleDetailDTO.parse_obj(el) for el in res.json()] == [role.to_dto()] + assert [RoleDetailDTO.model_validate(el) for el in res.json()] == [role.to_dto()] @pytest.mark.unit_test @@ -351,7 +365,7 @@ def test_role_create() -> None: ) assert res.status_code == 200 - assert RoleDetailDTO.parse_obj(res.json()) == role.to_dto().dict() + assert RoleDetailDTO.model_validate(res.json()) == role.to_dto() @pytest.mark.unit_test @@ -391,10 +405,10 @@ def test_bot_create() -> None: service.save_bot.return_value = bot service.get_group.return_value = Group(id="group", name="group") - print(create.json()) + create.model_dump_json() app = create_app(service) client = TestClient(app) - res = client.post("/v1/bots", headers=create_auth_token(app), json=create.dict()) + res = client.post("/v1/bots", headers=create_auth_token(app), json=create.model_dump()) assert res.status_code == 200 assert len(res.json().split(".")) == 3 @@ -410,7 +424,7 @@ def test_bot() -> None: client = TestClient(app) res = client.get("/v1/bots/0", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == bot.to_dto().dict() + assert res.json() == bot.to_dto().model_dump() @pytest.mark.unit_test @@ -424,11 +438,11 @@ def test_all_bots() -> None: client = TestClient(app) res = client.get("/v1/bots", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == [b.to_dto().dict() for b in bots] + assert res.json() == [b.to_dto().model_dump() for b in bots] res = client.get("/v1/bots?owner=4", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == [b.to_dto().dict() for b in bots] + assert res.json() == [b.to_dto().model_dump() for b in bots] service.get_all_bots.assert_called_once() service.get_all_bots_by_owner.assert_called_once() diff --git a/tests/matrixstore/__init__.py b/tests/matrixstore/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/matrixstore/__init__.py +++ b/tests/matrixstore/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/matrixstore/conftest.py b/tests/matrixstore/conftest.py index 745fff9aec..52285fb6f8 100644 --- a/tests/matrixstore/conftest.py +++ b/tests/matrixstore/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import unittest.mock import pytest diff --git a/tests/matrixstore/test_matrix_editor.py b/tests/matrixstore/test_matrix_editor.py index 2907cfb793..229e9e53f3 100644 --- a/tests/matrixstore/test_matrix_editor.py +++ b/tests/matrixstore/test_matrix_editor.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Any, Dict import pytest @@ -70,7 +82,7 @@ class TestMatrixSlice: ) def test_init(self, kwargs: Dict[str, Any], expected: Dict[str, Any]) -> None: obj = MatrixSlice(**kwargs) - assert obj.dict(by_alias=False) == expected + assert obj.model_dump(by_alias=False) == expected class TestOperation: @@ -97,12 +109,12 @@ class TestOperation: ) def test_init(self, kwargs: Dict[str, Any], expected: Dict[str, Any]) -> None: obj = Operation(**kwargs) - assert obj.dict(by_alias=False) == expected + assert obj.model_dump(by_alias=False) == expected @pytest.mark.parametrize("operation", list(OPERATIONS)) def test_init__valid_operation(self, operation: str) -> None: obj = Operation(operation=operation, value=123) - assert obj.dict(by_alias=False) == { + assert obj.model_dump(by_alias=False) == { "operation": operation, "value": 123.0, } @@ -192,4 +204,4 @@ class TestMatrixEditInstruction: ) def test_init(self, kwargs: Dict[str, Any], expected: Dict[str, Any]) -> None: obj = MatrixEditInstruction(**kwargs) - assert obj.dict(by_alias=False) == expected + assert obj.model_dump(by_alias=False) == expected diff --git a/tests/matrixstore/test_matrix_garbage_collector.py b/tests/matrixstore/test_matrix_garbage_collector.py index 6f6a81a498..1e02731910 100644 --- a/tests/matrixstore/test_matrix_garbage_collector.py +++ b/tests/matrixstore/test_matrix_garbage_collector.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from datetime import datetime from pathlib import Path from unittest.mock import Mock diff --git a/tests/matrixstore/test_repository.py b/tests/matrixstore/test_repository.py index ba76b17fac..c343d8adc7 100644 --- a/tests/matrixstore/test_repository.py +++ b/tests/matrixstore/test_repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import typing as t from pathlib import Path diff --git a/tests/matrixstore/test_service.py b/tests/matrixstore/test_service.py index 5c6eb837c7..65ce952e1d 100644 --- a/tests/matrixstore/test_service.py +++ b/tests/matrixstore/test_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import io import json @@ -485,12 +497,8 @@ def test_dataset_lifecycle() -> None: dataset_repo.delete.assert_called_once() -def _create_upload_file(filename: str, file: io.BytesIO, content_type: str = "") -> UploadFile: - if hasattr(UploadFile, "content_type"): - # `content_type` attribute was replace by a read-ony property in starlette-v0.24. - headers = Headers(headers={"content-type": content_type}) - # noinspection PyTypeChecker,PyArgumentList - return UploadFile(filename=filename, file=file, headers=headers) - else: - # noinspection PyTypeChecker,PyArgumentList - return UploadFile(filename=filename, file=file, content_type=content_type) +def _create_upload_file(filename: str, file: t.IO = None, content_type: str = "") -> UploadFile: + # `content_type` attribute was replace by a read-ony property in starlette-v0.24. + headers = Headers(headers={"content-type": content_type}) + # noinspection PyTypeChecker,PyArgumentList + return UploadFile(filename=filename, file=file, headers=headers) diff --git a/tests/matrixstore/test_web.py b/tests/matrixstore/test_web.py index 36b7fc366d..d47fb030bc 100644 --- a/tests/matrixstore/test_web.py +++ b/tests/matrixstore/test_web.py @@ -1,12 +1,25 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock import pytest from fastapi import FastAPI -from fastapi_jwt_auth import AuthJWT from starlette.testclient import TestClient +from antarest.core.application import create_app_ctxt from antarest.core.config import Config, SecurityConfig +from antarest.fastapi_jwt_auth import AuthJWT from antarest.main import JwtSettings from antarest.matrixstore.main import build_matrix_service from antarest.matrixstore.model import MatrixDTO, MatrixInfoDTO @@ -14,7 +27,7 @@ def create_app(service: Mock, auth_disabled=False) -> FastAPI: - app = FastAPI(title=__name__) + build_ctxt = create_app_ctxt(FastAPI(title=__name__)) @AuthJWT.load_config def get_config(): @@ -25,7 +38,7 @@ def get_config(): ) build_matrix_service( - app, + build_ctxt, user_service=Mock(), file_transfer_manager=Mock(), task_service=Mock(), @@ -35,7 +48,7 @@ def get_config(): security=SecurityConfig(disabled=auth_disabled), ), ) - return app + return build_ctxt.build() @pytest.mark.unit_test @@ -62,7 +75,7 @@ def test_create() -> None: json=matrix_data, ) assert res.status_code == 200 - assert res.json() == matrix.dict() + assert res.json() == matrix.model_dump() @pytest.mark.unit_test @@ -84,7 +97,7 @@ def test_get() -> None: client = TestClient(app) res = client.get("/v1/matrix/123", headers=create_auth_token(app)) assert res.status_code == 200 - assert res.json() == matrix.dict() + assert res.json() == matrix.model_dump() service.get.assert_called_once_with("123") @@ -114,4 +127,4 @@ def test_import() -> None: files={"file": ("Matrix.zip", bytes(5), "application/zip")}, ) assert res.status_code == 200 - assert res.json() == matrix_info + assert [MatrixInfoDTO.model_validate(res.json()[0])] == matrix_info diff --git a/tests/storage/__init__.py b/tests/storage/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/__init__.py +++ b/tests/storage/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/business/__init__.py b/tests/storage/business/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/business/__init__.py +++ b/tests/storage/business/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/business/assets/__init__.py b/tests/storage/business/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/storage/business/assets/__init__.py +++ b/tests/storage/business/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/storage/business/test_arealink_manager.py b/tests/storage/business/test_arealink_manager.py index a8beff5fc0..cb1d29c971 100644 --- a/tests/storage/business/test_arealink_manager.py +++ b/tests/storage/business/test_arealink_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import uuid from pathlib import Path @@ -162,35 +174,36 @@ def test_area_crud(empty_study: FileStudy, matrix_service: SimpleMatrixService): variant_id, [ CommandDTO( + id=None, action=CommandName.UPDATE_CONFIG.value, args=[ { "target": "input/areas/test/ui/ui/x", - "data": "100", + "data": 100, }, { "target": "input/areas/test/ui/ui/y", - "data": "200", + "data": 200, }, { "target": "input/areas/test/ui/ui/color_r", - "data": "255", + "data": 255, }, { "target": "input/areas/test/ui/ui/color_g", - "data": "0", + "data": 0, }, { "target": "input/areas/test/ui/ui/color_b", - "data": "100", + "data": 100, }, { "target": "input/areas/test/ui/layerX/0", - "data": "100", + "data": 100, }, { "target": "input/areas/test/ui/layerY/0", - "data": "200", + "data": 200, }, { "target": "input/areas/test/ui/layerColor/0", @@ -290,7 +303,7 @@ def test_get_all_area(): area_manager.patch_service = Mock() area_manager.patch_service.get.return_value = Patch( areas={"a1": PatchArea(country="fr")}, - thermal_clusters={"a1.a": PatchCluster.parse_obj({"code-oi": "1"})}, + thermal_clusters={"a1.a": PatchCluster.model_validate({"code-oi": "1"})}, ) file_tree_mock.get.side_effect = [ { @@ -350,7 +363,7 @@ def test_get_all_area(): }, ] areas = area_manager.get_all_areas(study, AreaType.AREA) - assert expected_areas == [area.dict() for area in areas] + assert expected_areas == [area.model_dump() for area in areas] expected_clusters = [ { @@ -363,7 +376,7 @@ def test_get_all_area(): } ] clusters = area_manager.get_all_areas(study, AreaType.DISTRICT) - assert expected_clusters == [area.dict() for area in clusters] + assert expected_clusters == [area.model_dump() for area in clusters] file_tree_mock.get.side_effect = [{}, {}, {}] expected_all = [ @@ -401,14 +414,14 @@ def test_get_all_area(): }, ] all_areas = area_manager.get_all_areas(study) - assert expected_all == [area.dict() for area in all_areas] + assert expected_all == [area.model_dump() for area in all_areas] links = link_manager.get_all_links(study) assert [ {"area1": "a1", "area2": "a2", "ui": None}, {"area1": "a1", "area2": "a3", "ui": None}, {"area1": "a2", "area2": "a3", "ui": None}, - ] == [link.dict() for link in links] + ] == [link.model_dump() for link in links] def test_update_area(): @@ -451,7 +464,7 @@ def test_update_area(): new_area_info = area_manager.update_area_metadata(study, "a1", PatchArea(country="fr")) assert new_area_info.id == "a1" - assert new_area_info.metadata == {"country": "fr", "tags": []} + assert new_area_info.metadata.model_dump() == {"country": "fr", "tags": []} def test_update_clusters(): @@ -484,7 +497,7 @@ def test_update_clusters(): area_manager.patch_service = Mock() area_manager.patch_service.get.return_value = Patch( areas={"a1": PatchArea(country="fr")}, - thermal_clusters={"a1.a": PatchCluster.parse_obj({"code-oi": "1"})}, + thermal_clusters={"a1.a": PatchCluster.model_validate({"code-oi": "1"})}, ) file_tree_mock.get.side_effect = [ { diff --git a/tests/storage/business/test_autoarchive_service.py b/tests/storage/business/test_autoarchive_service.py index 48e2c537b7..559126f00d 100644 --- a/tests/storage/business/test_autoarchive_service.py +++ b/tests/storage/business/test_autoarchive_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/business/test_config_manager.py b/tests/storage/business/test_config_manager.py index f4d344a27d..f89a4438be 100644 --- a/tests/storage/business/test_config_manager.py +++ b/tests/storage/business/test_config_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock @@ -19,7 +31,7 @@ def test_thematic_trimming_config() -> None: - command_context = CommandContext.construct() + command_context = CommandContext.model_construct() command_factory_mock = Mock() command_factory_mock.command_context = command_context raw_study_service = Mock(spec=RawStudyService) @@ -54,27 +66,27 @@ def test_thematic_trimming_config() -> None: study.version = config.version = 700 actual = thematic_trimming_manager.get_field_values(study) - fields_info = get_fields_info(study.version) + fields_info = get_fields_info(int(study.version)) expected = ThematicTrimmingFormFields(**dict.fromkeys(fields_info, True)) assert actual == expected study.version = config.version = 800 actual = thematic_trimming_manager.get_field_values(study) - fields_info = get_fields_info(study.version) + fields_info = get_fields_info(int(study.version)) expected = ThematicTrimmingFormFields(**dict.fromkeys(fields_info, True)) expected.avl_dtg = False assert actual == expected study.version = config.version = 820 actual = thematic_trimming_manager.get_field_values(study) - fields_info = get_fields_info(study.version) + fields_info = get_fields_info(int(study.version)) expected = ThematicTrimmingFormFields(**dict.fromkeys(fields_info, True)) expected.avl_dtg = False assert actual == expected study.version = config.version = 830 actual = thematic_trimming_manager.get_field_values(study) - fields_info = get_fields_info(study.version) + fields_info = get_fields_info(int(study.version)) expected = ThematicTrimmingFormFields(**dict.fromkeys(fields_info, True)) expected.dens = False expected.profit_by_plant = False @@ -82,7 +94,7 @@ def test_thematic_trimming_config() -> None: study.version = config.version = 840 actual = thematic_trimming_manager.get_field_values(study) - fields_info = get_fields_info(study.version) + fields_info = get_fields_info(int(study.version)) expected = ThematicTrimmingFormFields(**dict.fromkeys(fields_info, False)) expected.cong_fee_alg = True assert actual == expected diff --git a/tests/storage/business/test_export.py b/tests/storage/business/test_export.py index 759bc99ed3..667f357ab9 100644 --- a/tests/storage/business/test_export.py +++ b/tests/storage/business/test_export.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock from zipfile import ZipFile diff --git a/tests/storage/business/test_import.py b/tests/storage/business/test_import.py index 2cd08eeba9..ddf984dc06 100644 --- a/tests/storage/business/test_import.py +++ b/tests/storage/business/test_import.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import os import shutil diff --git a/tests/storage/business/test_patch_service.py b/tests/storage/business/test_patch_service.py index ed7dd6c444..3abb8790f0 100644 --- a/tests/storage/business/test_patch_service.py +++ b/tests/storage/business/test_patch_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import json import uuid @@ -182,7 +194,7 @@ def test_set_output_ref(self, tmp_path: Path): additional_data=StudyAdditionalData( author="john.doe", horizon="foo-horizon", - patch=patch_outputs.json(), + patch=patch_outputs.model_dump_json(), ), archived=False, owner=None, diff --git a/tests/storage/business/test_raw_study_service.py b/tests/storage/business/test_raw_study_service.py index 2b5c4b2dfd..9364edfa14 100644 --- a/tests/storage/business/test_raw_study_service.py +++ b/tests/storage/business/test_raw_study_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import os import platform diff --git a/tests/storage/business/test_repository.py b/tests/storage/business/test_repository.py index 5da1d6ef33..ed025de372 100644 --- a/tests/storage/business/test_repository.py +++ b/tests/storage/business/test_repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime from unittest.mock import Mock diff --git a/tests/storage/business/test_study_service_utils.py b/tests/storage/business/test_study_service_utils.py index dcd674e0e3..fd89592d65 100644 --- a/tests/storage/business/test_study_service_utils.py +++ b/tests/storage/business/test_study_service_utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import tarfile from hashlib import md5 diff --git a/tests/storage/business/test_study_version_upgrader.py b/tests/storage/business/test_study_version_upgrader.py index f406070308..39ce1da653 100644 --- a/tests/storage/business/test_study_version_upgrader.py +++ b/tests/storage/business/test_study_version_upgrader.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import filecmp import glob import os @@ -176,7 +188,7 @@ def assert_settings_are_updated(tmp_path: Path, old_values: List[str]) -> None: assert adequacy_patch["threshold-initiate-curtailment-sharing-rule"] == 0.0 assert adequacy_patch["threshold-display-local-matching-rule-violations"] == 0.0 assert adequacy_patch["threshold-csr-variable-bounds-relaxation"] == 3 - assert adequacy_patch["enable-first-step"] + assert not adequacy_patch["enable-first-step"] def get_old_settings_values(tmp_path: Path) -> List[str]: diff --git a/tests/storage/business/test_timeseries_config_manager.py b/tests/storage/business/test_timeseries_config_manager.py index 387e42f5dc..3bc7cd0ad9 100644 --- a/tests/storage/business/test_timeseries_config_manager.py +++ b/tests/storage/business/test_timeseries_config_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os import uuid from pathlib import Path @@ -44,7 +56,7 @@ def file_study_720(tmpdir: Path) -> FileStudy: def test_ts_field_values(file_study_820: FileStudy, file_study_720: FileStudy): command_factory_mock = Mock() - command_factory_mock.command_context = CommandContext.construct() + command_factory_mock.command_context = CommandContext.model_construct() raw_study_service = Mock(spec=RawStudyService) diff --git a/tests/storage/business/test_url_resolver_service.py b/tests/storage/business/test_url_resolver_service.py index 40dabc53c4..a7f6a601c5 100644 --- a/tests/storage/business/test_url_resolver_service.py +++ b/tests/storage/business/test_url_resolver_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os from unittest.mock import Mock diff --git a/tests/storage/business/test_variant_study_service.py b/tests/storage/business/test_variant_study_service.py index 7c6e00f99c..3a8a62b971 100644 --- a/tests/storage/business/test_variant_study_service.py +++ b/tests/storage/business/test_variant_study_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/business/test_watcher.py b/tests/storage/business/test_watcher.py index 6faeeabfe5..699a48f2c0 100644 --- a/tests/storage/business/test_watcher.py +++ b/tests/storage/business/test_watcher.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os from multiprocessing import Pool from pathlib import Path diff --git a/tests/storage/business/test_xpansion_manager.py b/tests/storage/business/test_xpansion_manager.py index 100bddd286..9c4cc56e07 100644 --- a/tests/storage/business/test_xpansion_manager.py +++ b/tests/storage/business/test_xpansion_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import os import typing as t @@ -197,7 +209,7 @@ def test_get_xpansion_settings(tmp_path: Path, version: int, expected_output: JS xpansion_manager.create_xpansion_configuration(study) actual = xpansion_manager.get_xpansion_settings(study) - assert actual.dict(by_alias=True) == expected_output + assert actual.model_dump(by_alias=True) == expected_output @pytest.mark.unit_test @@ -244,7 +256,7 @@ def test_update_xpansion_settings(tmp_path: Path) -> None: "timelimit": int(1e12), "sensitivity_config": {"epsilon": 10500.0, "projection": ["foo"], "capex": False}, } - assert actual.dict(by_alias=True) == expected + assert actual.model_dump(by_alias=True) == expected @pytest.mark.unit_test @@ -254,7 +266,7 @@ def test_add_candidate(tmp_path: Path) -> None: actual = empty_study.tree.get(["user", "expansion", "candidates"]) assert actual == {} - new_candidate = XpansionCandidateDTO.parse_obj( + new_candidate = XpansionCandidateDTO.model_validate( { "name": "candidate_1", "link": "area1 - area2", @@ -263,7 +275,7 @@ def test_add_candidate(tmp_path: Path) -> None: } ) - new_candidate2 = XpansionCandidateDTO.parse_obj( + new_candidate2 = XpansionCandidateDTO.model_validate( { "name": "candidate_2", "link": "area1 - area2", @@ -284,13 +296,13 @@ def test_add_candidate(tmp_path: Path) -> None: xpansion_manager.add_candidate(study, new_candidate) - candidates = {"1": new_candidate.dict(by_alias=True, exclude_none=True)} + candidates = {"1": new_candidate.model_dump(by_alias=True, exclude_none=True)} actual = empty_study.tree.get(["user", "expansion", "candidates"]) assert actual == candidates xpansion_manager.add_candidate(study, new_candidate2) - candidates["2"] = new_candidate2.dict(by_alias=True, exclude_none=True) + candidates["2"] = new_candidate2.model_dump(by_alias=True, exclude_none=True) actual = empty_study.tree.get(["user", "expansion", "candidates"]) assert actual == candidates @@ -302,7 +314,7 @@ def test_get_candidate(tmp_path: Path) -> None: assert empty_study.tree.get(["user", "expansion", "candidates"]) == {} - new_candidate = XpansionCandidateDTO.parse_obj( + new_candidate = XpansionCandidateDTO.model_validate( { "name": "candidate_1", "link": "area1 - area2", @@ -311,7 +323,7 @@ def test_get_candidate(tmp_path: Path) -> None: } ) - new_candidate2 = XpansionCandidateDTO.parse_obj( + new_candidate2 = XpansionCandidateDTO.model_validate( { "name": "candidate_2", "link": "area1 - area2", @@ -335,7 +347,7 @@ def test_get_candidates(tmp_path: Path) -> None: assert empty_study.tree.get(["user", "expansion", "candidates"]) == {} - new_candidate = XpansionCandidateDTO.parse_obj( + new_candidate = XpansionCandidateDTO.model_validate( { "name": "candidate_1", "link": "area1 - area2", @@ -344,7 +356,7 @@ def test_get_candidates(tmp_path: Path) -> None: } ) - new_candidate2 = XpansionCandidateDTO.parse_obj( + new_candidate2 = XpansionCandidateDTO.model_validate( { "name": "candidate_2", "link": "area1 - area2", @@ -372,7 +384,7 @@ def test_update_candidates(tmp_path: Path) -> None: make_link_and_areas(empty_study) - new_candidate = XpansionCandidateDTO.parse_obj( + new_candidate = XpansionCandidateDTO.model_validate( { "name": "candidate_1", "link": "area1 - area2", @@ -382,7 +394,7 @@ def test_update_candidates(tmp_path: Path) -> None: ) xpansion_manager.add_candidate(study, new_candidate) - new_candidate2 = XpansionCandidateDTO.parse_obj( + new_candidate2 = XpansionCandidateDTO.model_validate( { "name": "candidate_1", "link": "area1 - area2", @@ -403,7 +415,7 @@ def test_delete_candidate(tmp_path: Path) -> None: make_link_and_areas(empty_study) - new_candidate = XpansionCandidateDTO.parse_obj( + new_candidate = XpansionCandidateDTO.model_validate( { "name": "candidate_1", "link": "area1 - area2", @@ -413,7 +425,7 @@ def test_delete_candidate(tmp_path: Path) -> None: ) xpansion_manager.add_candidate(study, new_candidate) - new_candidate2 = XpansionCandidateDTO.parse_obj( + new_candidate2 = XpansionCandidateDTO.model_validate( { "name": "candidate_2", "link": "area1 - area2", @@ -488,29 +500,18 @@ def test_add_resources(tmp_path: Path) -> None: settings = xpansion_manager.get_xpansion_settings(study) settings.yearly_weights = filename3 - update_settings = UpdateXpansionSettings(**settings.dict()) + update_settings = UpdateXpansionSettings(**settings.model_dump()) xpansion_manager.update_xpansion_settings(study, update_settings) with pytest.raises(FileCurrentlyUsedInSettings): xpansion_manager.delete_resource(study, XpansionResourceFileType.WEIGHTS, filename3) settings.yearly_weights = "" - update_settings = UpdateXpansionSettings(**settings.dict()) + update_settings = UpdateXpansionSettings(**settings.model_dump()) xpansion_manager.update_xpansion_settings(study, update_settings) xpansion_manager.delete_resource(study, XpansionResourceFileType.WEIGHTS, filename3) -@pytest.mark.unit_test -def test_list_root_resources(tmp_path: Path) -> None: - empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) - - constraints_file_content = b"0" - constraints_file_name = "unknownfile.txt" - - empty_study.tree.save({"user": {"expansion": {constraints_file_name: constraints_file_content}}}) - assert [constraints_file_name] == xpansion_manager.list_root_files(study) - - @pytest.mark.unit_test def test_get_single_constraints(tmp_path: Path) -> None: empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) diff --git a/tests/storage/conftest.py b/tests/storage/conftest.py index a690f808df..ee8ce55684 100644 --- a/tests/storage/conftest.py +++ b/tests/storage/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import uuid from pathlib import Path diff --git a/tests/storage/integration/conftest.py b/tests/storage/integration/conftest.py index 39636961cb..dcf7e5e830 100644 --- a/tests/storage/integration/conftest.py +++ b/tests/storage/integration/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime from pathlib import Path from unittest.mock import Mock @@ -97,7 +109,7 @@ def storage_service(tmp_path: Path, project_path: Path, sta_mini_zip_path: Path) ) matrix_service = SimpleMatrixService(matrix_content_repository=matrix_content_repository) storage_service = build_study_service( - application=Mock(), + app_ctxt=Mock(), cache=LocalCache(config=config.cache), file_transfer_manager=Mock(), task_service=task_service_mock, diff --git a/tests/storage/integration/data/__init__.py b/tests/storage/integration/data/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/integration/data/__init__.py +++ b/tests/storage/integration/data/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/integration/data/de_details_hourly.py b/tests/storage/integration/data/de_details_hourly.py index c3ee8e3971..779c794bb6 100644 --- a/tests/storage/integration/data/de_details_hourly.py +++ b/tests/storage/integration/data/de_details_hourly.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + de_details_hourly = { "columns": [ ("01_solar", "MWh", ""), diff --git a/tests/storage/integration/data/de_fr_values_hourly.py b/tests/storage/integration/data/de_fr_values_hourly.py index 556985fbee..43a40c2e12 100644 --- a/tests/storage/integration/data/de_fr_values_hourly.py +++ b/tests/storage/integration/data/de_fr_values_hourly.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy de_fr_values_hourly = { diff --git a/tests/storage/integration/data/digest_file.py b/tests/storage/integration/data/digest_file.py index 363d2819bd..932be1eedd 100644 --- a/tests/storage/integration/data/digest_file.py +++ b/tests/storage/integration/data/digest_file.py @@ -1,2 +1,14 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + # fmt: off digest_file = {'columns': [str(i) for i in range(54)], 'data': [['', 'digest', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'VARIABLES', 'AREAS', 'LINKS', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '53', '4', '0', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', 'OV. COST', 'OP. COST', 'MRG. PRICE', 'CO2 EMIS.', 'BALANCE', 'ROW BAL.', 'PSP', 'MISC. NDG', 'LOAD', 'H. ROR', 'WIND', 'SOLAR', 'NUCLEAR', 'LIGNITE', 'COAL', 'GAS', 'OIL', 'MIX. FUEL', 'MISC. DTG', 'H. STOR', 'H. PUMP', 'H. LEV', 'H. INFL', 'H. OVFL', 'H. VAL', 'H. COST', 'UNSP. ENRG', 'SPIL. ENRG', 'LOLD', 'LOLP', 'AVL DTG', 'DTG MRG', 'MAX MRG', 'NP COST', '01_solar', '02_wind_on', '03_wind_off', '04_res', '05_nuclear', '06_coal', '07_gas', '08_non-res', '09_hydro_pump', 'NODU', '01_solar', '02_wind_on', '03_wind_off', '04_res', '05_nuclear', '06_coal', '07_gas', '08_non-res', '09_hydro_pump'], ['', '', 'Euro', 'Euro', 'Euro', 'Tons', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', 'MWh', '%', 'MWh', '%', 'Euro/MWh', 'Euro', 'MWh', 'MWh', 'Hours', '%', 'MWh', 'MWh', 'MWh', 'Euro', 'NP Cost - Euro', 'NP Cost - Euro', 'NP Cost - Euro', 'NP Cost - Euro', 'NP Cost - Euro', 'NP Cost - Euro', 'NP Cost - Euro', 'NP Cost - Euro', 'NP Cost - Euro', ' ', 'NODU', 'NODU', 'NODU', 'NODU', 'NODU', 'NODU', 'NODU', 'NODU', 'NODU'], ['', '', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'values', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'values', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP', 'EXP'], ['', 'de', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'N/A', '0', '0', 'N/A', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'], ['', 'es', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'N/A', '0', '0', 'N/A', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'], ['', 'fr', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'N/A', '0', '0', 'N/A', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'], ['', 'it', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'N/A', '0', '0', 'N/A', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'digest', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'VARIABLES', 'AREAS', 'LINKS', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '0', '0', '0', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'Links (FLOW LIN.)', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', 'From...', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '...To', 'de', 'es', 'fr', 'it', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'de', 'X', '--', '0', '--', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'es', '--', 'X', '0', '--', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'fr', '0', '0', 'X', '0', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'it', '--', '--', '0', 'X', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'Links (FLOW QUAD.)', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '', 'From...', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', '...To', 'de', 'es', 'fr', 'it', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'de', 'X', '--', '0', '--', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'es', '--', 'X', '0', '--', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'fr', '0', '0', 'X', '0', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], ['', 'it', '--', '--', '0', 'X', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']]} diff --git a/tests/storage/integration/data/set_id_annual.py b/tests/storage/integration/data/set_id_annual.py index dde1a172e0..353f2a03f5 100644 --- a/tests/storage/integration/data/set_id_annual.py +++ b/tests/storage/integration/data/set_id_annual.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import math set_id_annual = { diff --git a/tests/storage/integration/data/set_values_monthly.py b/tests/storage/integration/data/set_values_monthly.py index 0cc1ad2d32..efe6fe7052 100644 --- a/tests/storage/integration/data/set_values_monthly.py +++ b/tests/storage/integration/data/set_values_monthly.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import math set_values_monthly = { diff --git a/tests/storage/integration/test_STA_mini.py b/tests/storage/integration/test_STA_mini.py index f165c3c2dd..35aaa4092d 100644 --- a/tests/storage/integration/test_STA_mini.py +++ b/tests/storage/integration/test_STA_mini.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import shutil from datetime import datetime @@ -10,6 +22,7 @@ from fastapi import FastAPI from starlette.testclient import TestClient +from antarest.core.application import create_app_ctxt from antarest.core.jwt import DEFAULT_ADMIN_USER, JWTGroup, JWTUser from antarest.core.model import JSON from antarest.core.requests import RequestParameters @@ -34,19 +47,23 @@ ) -def assert_url_content(storage_service: StudyService, url: str, expected_output: dict) -> None: - app = FastAPI(title=__name__) +def create_test_client(service: StudyService) -> TestClient: + build_ctxt = create_app_ctxt(FastAPI(title=__name__)) build_study_service( - app, + build_ctxt, cache=Mock(), user_service=Mock(), task_service=Mock(), file_transfer_manager=Mock(), - study_service=storage_service, + study_service=service, matrix_service=Mock(spec=MatrixService), - config=storage_service.storage_service.raw_study_service.config, + config=service.storage_service.raw_study_service.config, ) - client = TestClient(app) + return TestClient(build_ctxt.build()) + + +def assert_url_content(storage_service: StudyService, url: str, expected_output: dict) -> None: + client = create_test_client(storage_service) res = client.get(url) assert_study(res.json(), expected_output) @@ -481,18 +498,7 @@ def test_sta_mini_copy(storage_service) -> None: source_study_name = UUID destination_study_name = "copy-STA-mini" - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - user_service=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - matrix_service=Mock(spec=MatrixService), - config=storage_service.storage_service.raw_study_service.config, - ) - client = TestClient(app) + client = create_test_client(storage_service) result = client.post(f"/v1/studies/{source_study_name}/copy?dest={destination_study_name}&use_task=false") assert result.status_code == HTTPStatus.CREATED.value @@ -578,18 +584,7 @@ def test_sta_mini_import(tmp_path: Path, storage_service) -> None: sta_mini_zip_filepath = shutil.make_archive(tmp_path, "zip", path_study) sta_mini_zip_path = Path(sta_mini_zip_filepath) - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - config=storage_service.storage_service.raw_study_service.config, - ) - client = TestClient(app) + client = create_test_client(storage_service) study_data = io.BytesIO(sta_mini_zip_path.read_bytes()) result = client.post("/v1/studies/_import", files={"study": study_data}) @@ -608,18 +603,7 @@ def test_sta_mini_import_output(tmp_path: Path, storage_service) -> None: sta_mini_output_zip_path = Path(sta_mini_output_zip_filepath) - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - config=storage_service.storage_service.raw_study_service.config, - ) - client = TestClient(app) + client = create_test_client(storage_service) study_output_data = io.BytesIO(sta_mini_output_zip_path.read_bytes()) result = client.post( diff --git a/tests/storage/integration/test_exporter.py b/tests/storage/integration/test_exporter.py index aed77f61fe..46e077a9ca 100644 --- a/tests/storage/integration/test_exporter.py +++ b/tests/storage/integration/test_exporter.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import json import zipfile @@ -9,6 +21,7 @@ from fastapi import FastAPI from starlette.testclient import TestClient +from antarest.core.application import create_app_ctxt from antarest.core.config import Config, SecurityConfig, StorageConfig, WorkspaceConfig from antarest.core.filetransfer.model import FileDownloadTaskDTO from antarest.core.jwt import DEFAULT_ADMIN_USER @@ -42,10 +55,10 @@ def assert_url_content(url: str, tmp_dir: Path, sta_mini_zip_path: Path) -> byte repo = Mock() repo.get.return_value = md - app = FastAPI(title=__name__) + build_ctxt = create_app_ctxt(FastAPI(title=__name__)) ftm = SimpleFileTransferManager(Config(storage=StorageConfig(tmp_dir=tmp_dir))) build_study_service( - app, + build_ctxt, cache=Mock(), user_service=Mock(), task_service=SimpleSyncTaskService(), @@ -57,7 +70,7 @@ def assert_url_content(url: str, tmp_dir: Path, sta_mini_zip_path: Path) -> byte ) # Simulate the download of data using a streamed request - client = TestClient(app) + client = TestClient(build_ctxt.build()) if client.stream is False: # `TestClient` is based on `Requests` (old way before AntaREST-v2.15) # noinspection PyArgumentList diff --git a/tests/storage/integration/test_write_STA_mini.py b/tests/storage/integration/test_write_STA_mini.py index 069d138e6c..302bbd6e52 100644 --- a/tests/storage/integration/test_write_STA_mini.py +++ b/tests/storage/integration/test_write_STA_mini.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import Optional import pytest diff --git a/tests/storage/rawstudies/__init__.py b/tests/storage/rawstudies/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/rawstudies/__init__.py +++ b/tests/storage/rawstudies/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/rawstudies/samples/__init__.py b/tests/storage/rawstudies/samples/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/storage/rawstudies/samples/__init__.py +++ b/tests/storage/rawstudies/samples/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/storage/rawstudies/test_factory.py b/tests/storage/rawstudies/test_factory.py index e2cd4391b3..80b2a2e19c 100644 --- a/tests/storage/rawstudies/test_factory.py +++ b/tests/storage/rawstudies/test_factory.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock from antarest.core.interfaces.cache import CacheConstants @@ -53,8 +65,8 @@ def test_factory_cache() -> None: cache.get.return_value = None study = factory.create_from_fs(path, study_id) assert study.config == config - cache.put.assert_called_once_with(cache_id, FileStudyTreeConfigDTO.from_build_config(config).dict()) + cache.put.assert_called_once_with(cache_id, FileStudyTreeConfigDTO.from_build_config(config).model_dump()) - cache.get.return_value = FileStudyTreeConfigDTO.from_build_config(config).dict() + cache.get.return_value = FileStudyTreeConfigDTO.from_build_config(config).model_dump() study = factory.create_from_fs(path, study_id) assert study.config == config diff --git a/tests/storage/rawstudies/test_helpers.py b/tests/storage/rawstudies/test_helpers.py index 789a39ca05..4f540d56be 100644 --- a/tests/storage/rawstudies/test_helpers.py +++ b/tests/storage/rawstudies/test_helpers.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock, call import pytest diff --git a/tests/storage/repository/__init__.py b/tests/storage/repository/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/__init__.py +++ b/tests/storage/repository/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/antares_io/__init__.py b/tests/storage/repository/antares_io/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/antares_io/__init__.py +++ b/tests/storage/repository/antares_io/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/antares_io/reader/test_ini_reader.py b/tests/storage/repository/antares_io/reader/test_ini_reader.py index 4ff38a32c6..6c1a18533a 100644 --- a/tests/storage/repository/antares_io/reader/test_ini_reader.py +++ b/tests/storage/repository/antares_io/reader/test_ini_reader.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import textwrap from pathlib import Path diff --git a/tests/storage/repository/antares_io/writer/test_ini_writer.py b/tests/storage/repository/antares_io/writer/test_ini_writer.py index b762469b7a..1affe2dc9c 100644 --- a/tests/storage/repository/antares_io/writer/test_ini_writer.py +++ b/tests/storage/repository/antares_io/writer/test_ini_writer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from typing import Callable diff --git a/tests/storage/repository/filesystem/__init__.py b/tests/storage/repository/filesystem/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/__init__.py +++ b/tests/storage/repository/filesystem/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/config/__init__.py b/tests/storage/repository/filesystem/config/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/config/__init__.py +++ b/tests/storage/repository/filesystem/config/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/config/test_config_files.py b/tests/storage/repository/filesystem/config/test_config_files.py index 93482d359d..a0fdf6d4f5 100644 --- a/tests/storage/repository/filesystem/config/test_config_files.py +++ b/tests/storage/repository/filesystem/config/test_config_files.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import logging import textwrap import typing as t @@ -403,7 +415,7 @@ def test_parse_thermal_860(study_path: Path, version, caplog) -> None: assert not caplog.text else: expected = [ThermalConfig(id="t1", name="t1")] - assert "extra fields not permitted" in caplog.text + assert "Extra inputs are not permitted" in caplog.text assert actual == expected diff --git a/tests/storage/repository/filesystem/config/test_files.py b/tests/storage/repository/filesystem/config/test_files.py index 99ed686280..fbdf160bce 100644 --- a/tests/storage/repository/filesystem/config/test_files.py +++ b/tests/storage/repository/filesystem/config/test_files.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import zipfile from pathlib import Path from unittest.mock import Mock, patch diff --git a/tests/storage/repository/filesystem/config/test_ruleset_matrices.py b/tests/storage/repository/filesystem/config/test_ruleset_matrices.py index 40651bce59..183a9481c8 100644 --- a/tests/storage/repository/filesystem/config/test_ruleset_matrices.py +++ b/tests/storage/repository/filesystem/config/test_ruleset_matrices.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import numpy as np diff --git a/tests/storage/repository/filesystem/config/test_utils.py b/tests/storage/repository/filesystem/config/test_utils.py index 617bc05ff0..cf470df38f 100644 --- a/tests/storage/repository/filesystem/config/test_utils.py +++ b/tests/storage/repository/filesystem/config/test_utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import string import pytest @@ -21,12 +33,12 @@ def test_transform_name_to_id__valid_chars(name): assert transform_name_to_id(name, lower=False) == name -@pytest.mark.parametrize("name", set(string.punctuation) - set(VALID_CHARS)) +@pytest.mark.parametrize("name", sorted(set(string.punctuation) - set(VALID_CHARS))) def test_transform_name_to_id__punctuation(name): assert not transform_name_to_id(name) -@pytest.mark.parametrize("name", set(string.whitespace) - set(VALID_CHARS)) +@pytest.mark.parametrize("name", sorted(set(string.whitespace) - set(VALID_CHARS))) def test_transform_name_to_id__whitespace(name): assert not transform_name_to_id(name) diff --git a/tests/storage/repository/filesystem/matrix/__init__.py b/tests/storage/repository/filesystem/matrix/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/matrix/__init__.py +++ b/tests/storage/repository/filesystem/matrix/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/matrix/test_date_serializer.py b/tests/storage/repository/filesystem/matrix/test_date_serializer.py index d9df33eb63..31ed6e8eab 100644 --- a/tests/storage/repository/filesystem/matrix/test_date_serializer.py +++ b/tests/storage/repository/filesystem/matrix/test_date_serializer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path import pandas as pd diff --git a/tests/storage/repository/filesystem/matrix/test_head_writer.py b/tests/storage/repository/filesystem/matrix/test_head_writer.py index e76d6b036b..bdc579a811 100644 --- a/tests/storage/repository/filesystem/matrix/test_head_writer.py +++ b/tests/storage/repository/filesystem/matrix/test_head_writer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.model.filesystem.matrix.head_writer import AreaHeadWriter, LinkHeadWriter diff --git a/tests/storage/repository/filesystem/matrix/test_input_series_matrix.py b/tests/storage/repository/filesystem/matrix/test_input_series_matrix.py index 1bc9df122a..153ce522e1 100644 --- a/tests/storage/repository/filesystem/matrix/test_input_series_matrix.py +++ b/tests/storage/repository/filesystem/matrix/test_input_series_matrix.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import itertools import shutil import textwrap diff --git a/tests/storage/repository/filesystem/matrix/test_matrix_node.py b/tests/storage/repository/filesystem/matrix/test_matrix_node.py index 6858a5ff0f..decac6e2e0 100644 --- a/tests/storage/repository/filesystem/matrix/test_matrix_node.py +++ b/tests/storage/repository/filesystem/matrix/test_matrix_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from tempfile import TemporaryDirectory from typing import List, Optional diff --git a/tests/storage/repository/filesystem/matrix/test_output_series_matrix.py b/tests/storage/repository/filesystem/matrix/test_output_series_matrix.py index e6eb256c51..8ed2a07fe0 100644 --- a/tests/storage/repository/filesystem/matrix/test_output_series_matrix.py +++ b/tests/storage/repository/filesystem/matrix/test_output_series_matrix.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/root/__init__.py b/tests/storage/repository/filesystem/root/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/__init__.py +++ b/tests/storage/repository/filesystem/root/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/input/__init__.py b/tests/storage/repository/filesystem/root/input/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/input/__init__.py +++ b/tests/storage/repository/filesystem/root/input/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/input/hydro/__init__.py b/tests/storage/repository/filesystem/root/input/hydro/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/input/hydro/__init__.py +++ b/tests/storage/repository/filesystem/root/input/hydro/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/input/hydro/common/__init__.py b/tests/storage/repository/filesystem/root/input/hydro/common/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/input/hydro/common/__init__.py +++ b/tests/storage/repository/filesystem/root/input/hydro/common/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/input/hydro/common/capacity/__init__.py b/tests/storage/repository/filesystem/root/input/hydro/common/capacity/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/input/hydro/common/capacity/__init__.py +++ b/tests/storage/repository/filesystem/root/input/hydro/common/capacity/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/input/hydro/common/capacity/test_capacity.py b/tests/storage/repository/filesystem/root/input/hydro/common/capacity/test_capacity.py index a6b45080ca..ee2fb3bdbf 100644 --- a/tests/storage/repository/filesystem/root/input/hydro/common/capacity/test_capacity.py +++ b/tests/storage/repository/filesystem/root/input/hydro/common/capacity/test_capacity.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import uuid from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/root/input/hydro/series/__init__.py b/tests/storage/repository/filesystem/root/input/hydro/series/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/input/hydro/series/__init__.py +++ b/tests/storage/repository/filesystem/root/input/hydro/series/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/input/hydro/series/area/__init__.py b/tests/storage/repository/filesystem/root/input/hydro/series/area/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/input/hydro/series/area/__init__.py +++ b/tests/storage/repository/filesystem/root/input/hydro/series/area/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/input/hydro/series/area/test_area.py b/tests/storage/repository/filesystem/root/input/hydro/series/area/test_area.py index 312f1d9b2a..4a1c7da570 100644 --- a/tests/storage/repository/filesystem/root/input/hydro/series/area/test_area.py +++ b/tests/storage/repository/filesystem/root/input/hydro/series/area/test_area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import uuid from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/root/output/__init__.py b/tests/storage/repository/filesystem/root/output/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/output/__init__.py +++ b/tests/storage/repository/filesystem/root/output/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/output/simulation/__init__.py b/tests/storage/repository/filesystem/root/output/simulation/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/output/simulation/__init__.py +++ b/tests/storage/repository/filesystem/root/output/simulation/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/output/simulation/mode/__init__.py b/tests/storage/repository/filesystem/root/output/simulation/mode/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/output/simulation/mode/__init__.py +++ b/tests/storage/repository/filesystem/root/output/simulation/mode/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/output/simulation/mode/common/__init__.py b/tests/storage/repository/filesystem/root/output/simulation/mode/common/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/root/output/simulation/mode/common/__init__.py +++ b/tests/storage/repository/filesystem/root/output/simulation/mode/common/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_area.py b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_area.py index 2ff4f6a44a..ca6a127e37 100644 --- a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_area.py +++ b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import uuid from pathlib import Path diff --git a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_binding_const.py b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_binding_const.py index 248468d5de..8ee6a31266 100644 --- a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_binding_const.py +++ b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_binding_const.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import uuid from pathlib import Path diff --git a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_link.py b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_link.py index 765187a186..28123774c5 100644 --- a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_link.py +++ b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_link.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import uuid from pathlib import Path diff --git a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_set.py b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_set.py index 0213647a8e..f6016deb7c 100644 --- a/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_set.py +++ b/tests/storage/repository/filesystem/root/output/simulation/mode/common/test_set.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import uuid from pathlib import Path diff --git a/tests/storage/repository/filesystem/special_node/__init__.py b/tests/storage/repository/filesystem/special_node/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/repository/filesystem/special_node/__init__.py +++ b/tests/storage/repository/filesystem/special_node/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/repository/filesystem/special_node/input_areas_list_test.py b/tests/storage/repository/filesystem/special_node/input_areas_list_test.py index 0616db9a5c..2bdf043763 100644 --- a/tests/storage/repository/filesystem/special_node/input_areas_list_test.py +++ b/tests/storage/repository/filesystem/special_node/input_areas_list_test.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/test_bucket_node.py b/tests/storage/repository/filesystem/test_bucket_node.py index 5cf61e53bb..1ea2ecf75f 100644 --- a/tests/storage/repository/filesystem/test_bucket_node.py +++ b/tests/storage/repository/filesystem/test_bucket_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/test_folder_node.py b/tests/storage/repository/filesystem/test_folder_node.py index ae017d7007..073fead252 100644 --- a/tests/storage/repository/filesystem/test_folder_node.py +++ b/tests/storage/repository/filesystem/test_folder_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json import textwrap import typing as t diff --git a/tests/storage/repository/filesystem/test_ini_file_node.py b/tests/storage/repository/filesystem/test_ini_file_node.py index 6808270c01..f4571d3ea9 100644 --- a/tests/storage/repository/filesystem/test_ini_file_node.py +++ b/tests/storage/repository/filesystem/test_ini_file_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import shutil import textwrap import typing as t diff --git a/tests/storage/repository/filesystem/test_lazy_node.py b/tests/storage/repository/filesystem/test_lazy_node.py index f899d32fa3..82e5cdeb0a 100644 --- a/tests/storage/repository/filesystem/test_lazy_node.py +++ b/tests/storage/repository/filesystem/test_lazy_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from typing import List, Optional from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/test_raw_file_node.py b/tests/storage/repository/filesystem/test_raw_file_node.py index 1232c575c3..04f2d6cb21 100644 --- a/tests/storage/repository/filesystem/test_raw_file_node.py +++ b/tests/storage/repository/filesystem/test_raw_file_node.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/test_scenariobuilder.py b/tests/storage/repository/filesystem/test_scenariobuilder.py index 91b964e621..bb65b140c5 100644 --- a/tests/storage/repository/filesystem/test_scenariobuilder.py +++ b/tests/storage/repository/filesystem/test_scenariobuilder.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/test_ts_numbers_vector.py b/tests/storage/repository/filesystem/test_ts_numbers_vector.py index a415bfddd8..f92383371e 100644 --- a/tests/storage/repository/filesystem/test_ts_numbers_vector.py +++ b/tests/storage/repository/filesystem/test_ts_numbers_vector.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock diff --git a/tests/storage/repository/filesystem/utils.py b/tests/storage/repository/filesystem/utils.py index cb563e8567..385802430f 100644 --- a/tests/storage/repository/filesystem/utils.py +++ b/tests/storage/repository/filesystem/utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from typing import List, Optional from zipfile import ZipFile diff --git a/tests/storage/repository/test_study.py b/tests/storage/repository/test_study.py index 7aa5fb23cd..43f51554a9 100644 --- a/tests/storage/repository/test_study.py +++ b/tests/storage/repository/test_study.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json from datetime import datetime diff --git a/tests/storage/study_upgrader/conftest.py b/tests/storage/study_upgrader/conftest.py index 8081ca70c9..4e17e64e22 100644 --- a/tests/storage/study_upgrader/conftest.py +++ b/tests/storage/study_upgrader/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing import zipfile from pathlib import Path diff --git a/tests/storage/study_upgrader/test_upgrade_710.py b/tests/storage/study_upgrader/test_upgrade_710.py index 6542cd3a3e..33763594b8 100644 --- a/tests/storage/study_upgrader/test_upgrade_710.py +++ b/tests/storage/study_upgrader/test_upgrade_710.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/study_upgrader/test_upgrade_720.py b/tests/storage/study_upgrader/test_upgrade_720.py index f2757b6fd5..61f6cea7ea 100644 --- a/tests/storage/study_upgrader/test_upgrade_720.py +++ b/tests/storage/study_upgrader/test_upgrade_720.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.business.test_study_version_upgrader import are_same_dir from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/study_upgrader/test_upgrade_800.py b/tests/storage/study_upgrader/test_upgrade_800.py index aded4de2c4..d03f483502 100644 --- a/tests/storage/study_upgrader/test_upgrade_800.py +++ b/tests/storage/study_upgrader/test_upgrade_800.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/study_upgrader/test_upgrade_810.py b/tests/storage/study_upgrader/test_upgrade_810.py index 2705798eb7..9ba51de57f 100644 --- a/tests/storage/study_upgrader/test_upgrade_810.py +++ b/tests/storage/study_upgrader/test_upgrade_810.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.business.test_study_version_upgrader import are_same_dir diff --git a/tests/storage/study_upgrader/test_upgrade_820.py b/tests/storage/study_upgrader/test_upgrade_820.py index d535a9b838..41cf4198d3 100644 --- a/tests/storage/study_upgrader/test_upgrade_820.py +++ b/tests/storage/study_upgrader/test_upgrade_820.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.business.test_study_version_upgrader import are_same_dir diff --git a/tests/storage/study_upgrader/test_upgrade_830.py b/tests/storage/study_upgrader/test_upgrade_830.py index c17e110d58..146029f17e 100644 --- a/tests/storage/study_upgrader/test_upgrade_830.py +++ b/tests/storage/study_upgrader/test_upgrade_830.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.business.test_study_version_upgrader import are_same_dir diff --git a/tests/storage/study_upgrader/test_upgrade_840.py b/tests/storage/study_upgrader/test_upgrade_840.py index 9cd39a3a49..b5b99ddae5 100644 --- a/tests/storage/study_upgrader/test_upgrade_840.py +++ b/tests/storage/study_upgrader/test_upgrade_840.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/study_upgrader/test_upgrade_850.py b/tests/storage/study_upgrader/test_upgrade_850.py index e40f00aa02..c4c040b5cb 100644 --- a/tests/storage/study_upgrader/test_upgrade_850.py +++ b/tests/storage/study_upgrader/test_upgrade_850.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/study_upgrader/test_upgrade_860.py b/tests/storage/study_upgrader/test_upgrade_860.py index 772589ee11..704c4aaf44 100644 --- a/tests/storage/study_upgrader/test_upgrade_860.py +++ b/tests/storage/study_upgrader/test_upgrade_860.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.business.test_study_version_upgrader import are_same_dir from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/study_upgrader/test_upgrade_870.py b/tests/storage/study_upgrader/test_upgrade_870.py index 4024e02fee..f4fb6721b6 100644 --- a/tests/storage/study_upgrader/test_upgrade_870.py +++ b/tests/storage/study_upgrader/test_upgrade_870.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.business.test_study_version_upgrader import are_same_dir from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/study_upgrader/test_upgrade_880.py b/tests/storage/study_upgrader/test_upgrade_880.py index b0868daec2..465092c4a8 100644 --- a/tests/storage/study_upgrader/test_upgrade_880.py +++ b/tests/storage/study_upgrader/test_upgrade_880.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.study_upgrader import StudyUpgrader from tests.storage.business.test_study_version_upgrader import are_same_dir from tests.storage.study_upgrader.conftest import StudyAssets diff --git a/tests/storage/test_model.py b/tests/storage/test_model.py index d17d6c89a4..f59ce30137 100644 --- a/tests/storage/test_model.py +++ b/tests/storage/test_model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency @@ -55,5 +67,5 @@ def test_file_study_tree_config_dto(): enr_modelling="aggregated", ) config_dto = FileStudyTreeConfigDTO.from_build_config(config) - assert sorted(list(config_dto.dict()) + ["cache"]) == sorted(list(config.__dict__)) + assert sorted(list(config_dto.model_dump()) + ["cache"]) == sorted(list(config.__dict__)) assert config_dto.to_build_config() == config diff --git a/tests/storage/test_service.py b/tests/storage/test_service.py index 7ebf94a09e..47ba9fe49c 100644 --- a/tests/storage/test_service.py +++ b/tests/storage/test_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import contextlib import os import textwrap @@ -585,7 +597,7 @@ def test_download_output() -> None: name="east", type=StudyDownloadType.AREA, data={ - 1: [ + "1": [ TimeSerie(name="H. VAL", unit="Euro/MWh", data=[0.5]), TimeSerie(name="some cluster", unit="Euro/MWh", data=[0.8]), ] @@ -649,7 +661,7 @@ def test_download_output() -> None: TimeSeriesData( name="east^west", type=StudyDownloadType.LINK, - data={1: [TimeSerie(name="H. VAL", unit="Euro/MWh", data=[0.5])]}, + data={"1": [TimeSerie(name="H. VAL", unit="Euro/MWh", data=[0.5])]}, ) ], warnings=[], @@ -683,7 +695,7 @@ def test_download_output() -> None: name="north", type=StudyDownloadType.DISTRICT, data={ - 1: [ + "1": [ TimeSerie(name="H. VAL", unit="Euro/MWh", data=[0.5]), TimeSerie(name="some cluster", unit="Euro/MWh", data=[0.8]), ] @@ -1379,7 +1391,7 @@ def test_unarchive_output(tmp_path: Path) -> None: src=str(tmp_path / "output" / f"{output_id}.zip"), dest=str(tmp_path / "output" / output_id), remove_src=False, - ).dict(), + ).model_dump(), name=f"Unarchive output {study_name}/{output_id} ({study_id})", ref_id=study_id, request_params=RequestParameters(user=DEFAULT_ADMIN_USER), @@ -1510,7 +1522,7 @@ def test_archive_output_locks(tmp_path: Path) -> None: src=str(tmp_path / "output" / f"{output_id}.zip"), dest=str(tmp_path / "output" / output_id), remove_src=False, - ).dict(), + ).model_dump(), name=f"Unarchive output {study_name}/{output_id} ({study_id})", ref_id=study_id, request_params=RequestParameters(user=DEFAULT_ADMIN_USER), diff --git a/tests/storage/web/__init__.py b/tests/storage/web/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/storage/web/__init__.py +++ b/tests/storage/web/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/storage/web/test_studies_bp.py b/tests/storage/web/test_studies_bp.py index 2ee0a9c7e2..33cedcc8df 100644 --- a/tests/storage/web/test_studies_bp.py +++ b/tests/storage/web/test_studies_bp.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import io import json import shutil @@ -12,9 +24,11 @@ from markupsafe import Markup from starlette.testclient import TestClient +from antarest.core.application import create_app_ctxt from antarest.core.config import Config, SecurityConfig, StorageConfig, WorkspaceConfig from antarest.core.exceptions import UrlNotMatchJsonDataError from antarest.core.filetransfer.model import FileDownloadDTO, FileDownloadTaskDTO +from antarest.core.filetransfer.service import FileTransferManager from antarest.core.jwt import JWTGroup, JWTUser from antarest.core.requests import RequestParameters from antarest.core.roles import RoleType @@ -36,6 +50,7 @@ TimeSerie, TimeSeriesData, ) +from antarest.study.service import StudyService from tests.storage.conftest import SimpleFileTransferManager from tests.storage.integration.conftest import UUID @@ -54,23 +69,29 @@ ) -@pytest.mark.unit_test -def test_server() -> None: - mock_service = Mock() - mock_service.get.return_value = {} - - app = FastAPI(title=__name__) +def create_test_client( + service: StudyService, file_transfer_manager: FileTransferManager = Mock(), raise_server_exceptions: bool = True +) -> TestClient: + app_ctxt = create_app_ctxt(FastAPI(title=__name__)) build_study_service( - app, + app_ctxt, cache=Mock(), task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_service, + file_transfer_manager=file_transfer_manager, + study_service=service, config=CONFIG, user_service=Mock(), matrix_service=Mock(spec=MatrixService), ) - client = TestClient(app) + return TestClient(app_ctxt.build(), raise_server_exceptions=raise_server_exceptions) + + +@pytest.mark.unit_test +def test_server() -> None: + mock_service = Mock() + mock_service.get.return_value = {} + + client = create_test_client(mock_service) client.get("/v1/studies/study1/raw?path=settings/general/params") mock_service.get.assert_called_once_with( @@ -83,18 +104,7 @@ def test_404() -> None: mock_storage_service = Mock() mock_storage_service.get.side_effect = UrlNotMatchJsonDataError("Test") - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app, raise_server_exceptions=False) + client = create_test_client(mock_storage_service, raise_server_exceptions=False) result = client.get("/v1/studies/study1/raw?path=settings/general/params") assert result.status_code == HTTPStatus.NOT_FOUND @@ -107,18 +117,7 @@ def test_server_with_parameters() -> None: mock_storage_service = Mock() mock_storage_service.get.return_value = {} - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(mock_storage_service) result = client.get("/v1/studies/study1/raw?depth=4") parameters = RequestParameters(user=ADMIN) @@ -146,18 +145,7 @@ def test_create_study(tmp_path: str, project_path) -> None: storage_service = Mock() storage_service.create_study.return_value = "my-uuid" - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(storage_service) result_right = client.post("/v1/studies?name=study2") @@ -181,18 +169,7 @@ def test_import_study_zipped(tmp_path: Path, project_path) -> None: study_uuid = str(uuid.uuid4()) mock_storage_service.import_study.return_value = study_uuid - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(mock_storage_service) result = client.post("/v1/studies") @@ -211,18 +188,7 @@ def test_copy_study(tmp_path: Path) -> None: storage_service = Mock() storage_service.copy_study.return_value = "/studies/study-copied" - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(storage_service) result = client.post(f"/v1/studies/{UUID}/copy?dest=study-copied") @@ -273,21 +239,10 @@ def test_list_studies(tmp_path: str) -> None: storage_service = Mock() storage_service.get_studies_information.return_value = studies - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(storage_service) result = client.get("/v1/studies") - assert {k: StudyMetadataDTO.parse_obj(v) for k, v in result.json().items()} == studies + assert {k: StudyMetadataDTO.model_validate(v) for k, v in result.json().items()} == studies def test_study_metadata(tmp_path: str) -> None: @@ -308,21 +263,10 @@ def test_study_metadata(tmp_path: str) -> None: storage_service = Mock() storage_service.get_study_information.return_value = study - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(storage_service) result = client.get("/v1/studies/1") - assert StudyMetadataDTO.parse_obj(result.json()) == study + assert StudyMetadataDTO.model_validate(result.json()) == study @pytest.mark.unit_test @@ -340,20 +284,8 @@ def test_export_files(tmp_path: Path) -> None: ) mock_storage_service.export_study.return_value = expected - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - # Simulate the download of data using a streamed request - client = TestClient(app) + client = create_test_client(mock_storage_service) if client.stream is False: # `TestClient` is based on `Requests` (old way before AntaREST-v2.15) # noinspection PyArgumentList @@ -370,7 +302,7 @@ def test_export_files(tmp_path: Path) -> None: res.raise_for_status() result = json.loads(data.getvalue()) - assert FileDownloadTaskDTO(**result).json() == expected.json() + assert FileDownloadTaskDTO(**result).model_dump_json() == expected.model_dump_json() mock_storage_service.export_study.assert_called_once_with(UUID, PARAMS, True) @@ -390,18 +322,7 @@ def test_export_params(tmp_path: Path) -> None: ) mock_storage_service.export_study.return_value = expected - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(mock_storage_service) client.get(f"/v1/studies/{UUID}/export?no_output=true") client.get(f"/v1/studies/{UUID}/export?no_output=false") mock_storage_service.export_study.assert_has_calls( @@ -416,18 +337,7 @@ def test_export_params(tmp_path: Path) -> None: def test_delete_study() -> None: mock_storage_service = Mock() - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(mock_storage_service) study_uuid = "8319b5f8-2a35-4984-9ace-2ab072bd6eef" client.delete(f"/v1/studies/{study_uuid}") @@ -440,18 +350,7 @@ def test_edit_study() -> None: mock_storage_service = Mock() mock_storage_service.edit_study.return_value = {} - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_storage_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app) + client = create_test_client(mock_storage_service) client.post("/v1/studies/my-uuid/raw?path=url/to/change", json={"Hello": "World"}) mock_storage_service.edit_study.assert_called_once_with("my-uuid", "url/to/change", {"Hello": "World"}, PARAMS) @@ -485,18 +384,7 @@ def test_validate() -> None: mock_service = Mock() mock_service.check_errors.return_value = ["Hello"] - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app, raise_server_exceptions=False) + client = create_test_client(mock_service, raise_server_exceptions=False) res = client.get("/v1/studies/my-uuid/raw/validate") assert res.json() == ["Hello"] @@ -539,24 +427,13 @@ def test_output_download(tmp_path: Path) -> None: synthesis=False, includeClusters=True, ) - - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=SimpleFileTransferManager(Config(storage=StorageConfig(tmp_dir=tmp_path))), - study_service=mock_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app, raise_server_exceptions=False) + ftm = SimpleFileTransferManager(Config(storage=StorageConfig(tmp_dir=tmp_path))) + client = create_test_client(mock_service, ftm, raise_server_exceptions=False) res = client.post( f"/v1/studies/{UUID}/outputs/my-output-id/download", - json=study_download.dict(), + json=study_download.model_dump(), ) - assert res.json() == output_data.dict() + assert res.json() == output_data.model_dump() @pytest.mark.unit_test @@ -576,18 +453,8 @@ def test_output_whole_download(tmp_path: Path) -> None: ) mock_service.export_output.return_value = expected - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=SimpleFileTransferManager(Config(storage=StorageConfig(tmp_dir=tmp_path))), - study_service=mock_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app, raise_server_exceptions=False) + ftm = SimpleFileTransferManager(Config(storage=StorageConfig(tmp_dir=tmp_path))) + client = create_test_client(mock_service, ftm, raise_server_exceptions=False) res = client.get( f"/v1/studies/{UUID}/outputs/{output_id}/export", ) @@ -600,18 +467,7 @@ def test_sim_reference() -> None: study_id = str(uuid.uuid4()) output_id = "my-output-id" - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app, raise_server_exceptions=False) + client = create_test_client(mock_service, raise_server_exceptions=False) res = client.put(f"/v1/studies/{study_id}/outputs/{output_id}/reference") mock_service.set_sim_reference.assert_called_once_with(study_id, output_id, True, PARAMS) assert res.status_code == HTTPStatus.OK @@ -644,38 +500,17 @@ def test_sim_result() -> None: ) ] mock_service.get_study_sim_result.return_value = result_data - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=mock_service, - config=CONFIG, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - ) - client = TestClient(app, raise_server_exceptions=False) + + client = create_test_client(mock_service, raise_server_exceptions=False) res = client.get(f"/v1/studies/{study_id}/outputs") - assert res.json() == result_data + actual_object = [StudySimResultDTO.parse_obj(res.json()[0])] + assert actual_object == result_data @pytest.mark.unit_test def test_study_permission_management(tmp_path: Path) -> None: storage_service = Mock() - - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=storage_service, - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - config=CONFIG, - ) - client = TestClient(app, raise_server_exceptions=False) + client = create_test_client(storage_service, raise_server_exceptions=False) result = client.put(f"/v1/studies/{UUID}/owner/2") storage_service.change_owner.assert_called_with( @@ -715,18 +550,7 @@ def test_study_permission_management(tmp_path: Path) -> None: @pytest.mark.unit_test def test_get_study_versions(tmp_path: Path) -> None: - app = FastAPI(title=__name__) - build_study_service( - app, - cache=Mock(), - task_service=Mock(), - file_transfer_manager=Mock(), - study_service=Mock(), - user_service=Mock(), - matrix_service=Mock(spec=MatrixService), - config=CONFIG, - ) - client = TestClient(app, raise_server_exceptions=False) + client = create_test_client(Mock(), raise_server_exceptions=False) result = client.get("/v1/studies/_versions") assert result.json() == list(STUDY_REFERENCE_TEMPLATES.keys()) diff --git a/tests/study/__init__.py b/tests/study/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/__init__.py +++ b/tests/study/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/business/__init__.py b/tests/study/business/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/business/__init__.py +++ b/tests/study/business/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/business/areas/__init__.py b/tests/study/business/areas/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/business/areas/__init__.py +++ b/tests/study/business/areas/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/business/areas/assets/__init__.py b/tests/study/business/areas/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/study/business/areas/assets/__init__.py +++ b/tests/study/business/areas/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/study/business/areas/test_st_storage_management.py b/tests/study/business/areas/test_st_storage_management.py index 74089bc7cd..56a42d88a0 100644 --- a/tests/study/business/areas/test_st_storage_management.py +++ b/tests/study/business/areas/test_st_storage_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import io import re @@ -64,6 +76,8 @@ "east": {"list": {}}, } +GEN = np.random.default_rng(1000) + class TestSTStorageManager: @pytest.fixture(name="study_storage_service") @@ -135,7 +149,7 @@ def test_get_all_storages__nominal_case( # Check actual = { - area_id: [form.dict(by_alias=True) for form in clusters_by_ids.values()] + area_id: [form.model_dump(by_alias=True) for form in clusters_by_ids.values()] for area_id, clusters_by_ids in all_storages.items() } expected = { @@ -241,7 +255,7 @@ def test_get_st_storages__nominal_case( groups = manager.get_storages(study, area_id="West") # Check - actual = [form.dict(by_alias=True) for form in groups] + actual = [form.model_dump(by_alias=True) for form in groups] expected = [ { "efficiency": 0.94, @@ -353,7 +367,7 @@ def test_get_st_storage__nominal_case( edit_form = manager.get_storage(study, area_id="West", storage_id="storage1") # Assert that the returned storage fields match the expected fields - actual = edit_form.dict(by_alias=True) + actual = edit_form.model_dump(by_alias=True) expected = { "efficiency": 0.94, "group": STStorageGroup.BATTERY, @@ -443,11 +457,11 @@ def test_update_storage__nominal_case( actual = {(call_args[0][0], tuple(call_args[0][1])) for call_args in file_study.tree.save.call_args_list} expected = { ( - str(0.0), + 0.0, ("input", "st-storage", "clusters", "West", "list", "storage1", "initiallevel"), ), ( - str(False), + False, ("input", "st-storage", "clusters", "West", "list", "storage1", "initialleveloptim"), ), } @@ -516,16 +530,15 @@ def test_get_matrix__nominal_case( # Prepare the mocks storage = study_storage_service.get_storage(study) file_study = storage.get_raw(study) - array = np.random.rand(8760, 1) * 1000 + array = GEN.random((8760, 1)) * 1000 + expected = { + "index": list(range(8760)), + "columns": [0], + "data": array.tolist(), + } file_study.tree = Mock( spec=FileStudyTree, - get=Mock( - return_value={ - "index": list(range(8760)), - "columns": [0], - "data": array.tolist(), - } - ), + get=Mock(return_value=expected), ) # Given the following arguments @@ -535,8 +548,8 @@ def test_get_matrix__nominal_case( matrix = manager.get_matrix(study, area_id="West", storage_id="storage1", ts_name="inflows") # Assert that the returned storage fields match the expected fields - actual = matrix.dict(by_alias=True) - assert actual == matrix + actual = matrix.model_dump(by_alias=True) + assert actual == expected def test_get_matrix__config_not_found( self, @@ -604,7 +617,7 @@ def test_get_matrix__invalid_matrix( # Prepare the mocks storage = study_storage_service.get_storage(study) file_study = storage.get_raw(study) - array = np.random.rand(365, 1) * 1000 + array = GEN.random((365, 1)) * 1000 matrix = { "index": list(range(365)), "columns": [0], @@ -637,11 +650,11 @@ def test_validate_matrices__nominal( # prepare some random matrices, insuring `lower_rule_curve` <= `upper_rule_curve` matrices = { - "pmax_injection": np.random.rand(8760, 1), - "pmax_withdrawal": np.random.rand(8760, 1), - "lower_rule_curve": np.random.rand(8760, 1) / 2, - "upper_rule_curve": np.random.rand(8760, 1) / 2 + 0.5, - "inflows": np.random.rand(8760, 1) * 1000, + "pmax_injection": GEN.random((8760, 1)), + "pmax_withdrawal": GEN.random((8760, 1)), + "lower_rule_curve": GEN.random((8760, 1)) / 2, + "upper_rule_curve": GEN.random((8760, 1)) / 2 + 0.5, + "inflows": GEN.random((8760, 1)) * 1000, } # Prepare the mocks @@ -674,11 +687,11 @@ def test_validate_matrices__out_of_bound( # prepare some random matrices, insuring `lower_rule_curve` <= `upper_rule_curve` matrices = { - "pmax_injection": np.random.rand(8760, 1) * 2 - 0.5, # out of bound - "pmax_withdrawal": np.random.rand(8760, 1) * 2 - 0.5, # out of bound - "lower_rule_curve": np.random.rand(8760, 1) * 2 - 0.5, # out of bound - "upper_rule_curve": np.random.rand(8760, 1) * 2 - 0.5, # out of bound - "inflows": np.random.rand(8760, 1) * 1000, + "pmax_injection": GEN.random((8760, 1)) * 2 - 0.5, # out of bound + "pmax_withdrawal": GEN.random((8760, 1)) * 2 - 0.5, # out of bound + "lower_rule_curve": GEN.random((8760, 1)) * 2 - 0.5, # out of bound + "upper_rule_curve": GEN.random((8760, 1)) * 2 - 0.5, # out of bound + "inflows": GEN.random((8760, 1)) * 1000, } # Prepare the mocks @@ -695,7 +708,6 @@ def tree_get(url: t.Sequence[str], **_: t.Any) -> t.MutableMapping[str, t.Any]: file_study = storage.get_raw(study) file_study.tree = Mock(spec=FileStudyTree, get=tree_get) - # Given the following arguments, the validation shouldn't raise any exception manager = STStorageManager(study_storage_service) # Run the method being tested and expect an exception @@ -704,29 +716,11 @@ def tree_get(url: t.Sequence[str], **_: t.Any) -> t.MutableMapping[str, t.Any]: match=re.escape("4 validation errors"), ) as ctx: manager.validate_matrices(study, area_id="West", storage_id="storage1") - errors = ctx.value.errors() - assert errors == [ - { - "loc": ("pmax_injection",), - "msg": "Matrix values should be between 0 and 1", - "type": "value_error", - }, - { - "loc": ("pmax_withdrawal",), - "msg": "Matrix values should be between 0 and 1", - "type": "value_error", - }, - { - "loc": ("lower_rule_curve",), - "msg": "Matrix values should be between 0 and 1", - "type": "value_error", - }, - { - "loc": ("upper_rule_curve",), - "msg": "Matrix values should be between 0 and 1", - "type": "value_error", - }, - ] + assert ctx.value.error_count() == 4 + for error in ctx.value.errors(): + assert error["type"] == "value_error" + assert error["msg"] == "Value error, Matrix values should be between 0 and 1" + assert error["loc"][0] in ["upper_rule_curve", "lower_rule_curve", "pmax_withdrawal", "pmax_injection"] # noinspection SpellCheckingInspection def test_validate_matrices__rule_curve( @@ -738,13 +732,15 @@ def test_validate_matrices__rule_curve( # The study must be fetched from the database study: RawStudy = db_session.query(Study).get(study_uuid) - # prepare some random matrices, insuring `lower_rule_curve` <= `upper_rule_curve` + # prepare some random matrices, not respecting `lower_rule_curve` <= `upper_rule_curve` + upper_curve = np.zeros((8760, 1)) + lower_curve = np.ones((8760, 1)) matrices = { - "pmax_injection": np.random.rand(8760, 1), - "pmax_withdrawal": np.random.rand(8760, 1), - "lower_rule_curve": np.random.rand(8760, 1), - "upper_rule_curve": np.random.rand(8760, 1), - "inflows": np.random.rand(8760, 1) * 1000, + "pmax_injection": GEN.random((8760, 1)), + "pmax_withdrawal": GEN.random((8760, 1)), + "lower_rule_curve": lower_curve, + "upper_rule_curve": upper_curve, + "inflows": GEN.random((8760, 1)) * 1000, } # Prepare the mocks @@ -761,7 +757,7 @@ def tree_get(url: t.Sequence[str], **_: t.Any) -> t.MutableMapping[str, t.Any]: file_study = storage.get_raw(study) file_study.tree = Mock(spec=FileStudyTree, get=tree_get) - # Given the following arguments, the validation shouldn't raise any exception + # Given the following arguments manager = STStorageManager(study_storage_service) # Run the method being tested and expect an exception @@ -771,6 +767,8 @@ def tree_get(url: t.Sequence[str], **_: t.Any) -> t.MutableMapping[str, t.Any]: ) as ctx: manager.validate_matrices(study, area_id="West", storage_id="storage1") error = ctx.value.errors()[0] - assert error["loc"] == ("__root__",) - assert "lower_rule_curve" in error["msg"] - assert "upper_rule_curve" in error["msg"] + assert error["type"] == "value_error" + assert ( + error["msg"] + == "Value error, Each 'lower_rule_curve' value must be lower or equal to each 'upper_rule_curve'" + ) diff --git a/tests/study/business/areas/test_thermal_management.py b/tests/study/business/areas/test_thermal_management.py index dd52ec9538..6bb2e34d7e 100644 --- a/tests/study/business/areas/test_thermal_management.py +++ b/tests/study/business/areas/test_thermal_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import re import shutil @@ -132,7 +144,7 @@ def test_get_cluster__study_legacy( form = manager.get_cluster(study, area_id="north", cluster_id="2 avail and must 1") # Assert that the returned fields match the expected fields - actual = form.dict(by_alias=True) + actual = form.model_dump(by_alias=True) expected = { "id": "2 avail and must 1", "group": ThermalClusterGroup.GAS, @@ -198,7 +210,7 @@ def test_get_clusters__study_legacy( groups = manager.get_clusters(study, area_id="north") # Assert that the returned fields match the expected fields - actual = [form.dict(by_alias=True) for form in groups] + actual = [form.model_dump(by_alias=True) for form in groups] expected = [ { "id": "2 avail and must 1", @@ -354,7 +366,7 @@ def test_create_cluster__study_legacy( form = manager.create_cluster(study, area_id="north", cluster_data=cluster_data) # Assert that the returned fields match the expected fields - actual = form.dict(by_alias=True) + actual = form.model_dump(by_alias=True) expected = { "co2": 12.59, "enabled": True, @@ -414,7 +426,7 @@ def test_update_cluster( # Assert that the returned fields match the expected fields form = manager.get_cluster(study, area_id="north", cluster_id="2 avail and must 1") - actual = form.dict(by_alias=True) + actual = form.model_dump(by_alias=True) expected = { "id": "2 avail and must 1", "group": ThermalClusterGroup.GAS, diff --git a/tests/study/business/test_all_optional_metaclass.py b/tests/study/business/test_all_optional_metaclass.py index 1c379f6460..b8d1197c5e 100644 --- a/tests/study/business/test_all_optional_metaclass.py +++ b/tests/study/business/test_all_optional_metaclass.py @@ -1,349 +1,60 @@ -import typing as t +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. -import pytest -from pydantic import BaseModel, Field, ValidationError +from pydantic import BaseModel, Field -from antarest.study.business.all_optional_meta import AllOptionalMetaclass +from antarest.study.business.all_optional_meta import all_optional_model, camel_case_model -# ============================================== -# Classic way to use default and optional values -# ============================================== +class Model(BaseModel): + float_with_default: float = 1 + float_without_default: float + boolean_with_default: bool = True + boolean_without_default: bool + field_with_alias: str = Field(default="default", alias="field-with-alias") -class ClassicModel(BaseModel): - mandatory: float = Field(ge=0, le=1) - mandatory_with_default: float = Field(ge=0, le=1, default=0.2) - mandatory_with_none: float = Field(ge=0, le=1, default=None) - optional: t.Optional[float] = Field(ge=0, le=1) - optional_with_default: t.Optional[float] = Field(ge=0, le=1, default=0.2) - optional_with_none: t.Optional[float] = Field(ge=0, le=1, default=None) - -class ClassicSubModel(ClassicModel): - pass - - -class TestClassicModel: - """ - Test that default and optional values work as expected. - """ - - @pytest.mark.parametrize("cls", [ClassicModel, ClassicSubModel]) - def test_classes(self, cls: t.Type[BaseModel]) -> None: - assert cls.__fields__["mandatory"].required is True - assert cls.__fields__["mandatory"].allow_none is False - assert cls.__fields__["mandatory"].default is None - assert cls.__fields__["mandatory"].default_factory is None # undefined - - assert cls.__fields__["mandatory_with_default"].required is False - assert cls.__fields__["mandatory_with_default"].allow_none is False - assert cls.__fields__["mandatory_with_default"].default == 0.2 - assert cls.__fields__["mandatory_with_default"].default_factory is None # undefined - - assert cls.__fields__["mandatory_with_none"].required is False - assert cls.__fields__["mandatory_with_none"].allow_none is True - assert cls.__fields__["mandatory_with_none"].default is None - assert cls.__fields__["mandatory_with_none"].default_factory is None # undefined - - assert cls.__fields__["optional"].required is False - assert cls.__fields__["optional"].allow_none is True - assert cls.__fields__["optional"].default is None - assert cls.__fields__["optional"].default_factory is None # undefined - - assert cls.__fields__["optional_with_default"].required is False - assert cls.__fields__["optional_with_default"].allow_none is True - assert cls.__fields__["optional_with_default"].default == 0.2 - assert cls.__fields__["optional_with_default"].default_factory is None # undefined - - assert cls.__fields__["optional_with_none"].required is False - assert cls.__fields__["optional_with_none"].allow_none is True - assert cls.__fields__["optional_with_none"].default is None - assert cls.__fields__["optional_with_none"].default_factory is None # undefined - - @pytest.mark.parametrize("cls", [ClassicModel, ClassicSubModel]) - def test_initialization(self, cls: t.Type[ClassicModel]) -> None: - # We can build a model without providing optional or default values. - # The initialized value will be the default value or `None` for optional values. - obj = cls(mandatory=0.5) - assert obj.mandatory == 0.5 - assert obj.mandatory_with_default == 0.2 - assert obj.mandatory_with_none is None - assert obj.optional is None - assert obj.optional_with_default == 0.2 - assert obj.optional_with_none is None - - # We must provide a value for mandatory fields. - with pytest.raises(ValidationError): - cls() - - @pytest.mark.parametrize("cls", [ClassicModel, ClassicSubModel]) - def test_validation(self, cls: t.Type[ClassicModel]) -> None: - # We CANNOT use `None` as a value for a field with a default value. - with pytest.raises(ValidationError): - cls(mandatory=0.5, mandatory_with_default=None) - - # We can use `None` as a value for optional fields with default value. - cls(mandatory=0.5, optional_with_default=None) - - # We can validate a model with valid values. - cls( - mandatory=0.5, - mandatory_with_default=0.2, - mandatory_with_none=0.2, - optional=0.5, - optional_with_default=0.2, - optional_with_none=0.2, - ) - - # We CANNOT validate a model with invalid values. - with pytest.raises(ValidationError): - cls(mandatory=2) - - with pytest.raises(ValidationError): - cls(mandatory=0.5, mandatory_with_default=2) - - with pytest.raises(ValidationError): - cls(mandatory=0.5, mandatory_with_none=2) - - with pytest.raises(ValidationError): - cls(mandatory=0.5, optional=2) - - with pytest.raises(ValidationError): - cls(mandatory=0.5, optional_with_default=2) - - with pytest.raises(ValidationError): - cls(mandatory=0.5, optional_with_none=2) - - -# ========================== -# Using AllOptionalMetaclass -# ========================== - - -class AllOptionalModel(BaseModel, metaclass=AllOptionalMetaclass): - mandatory: float = Field(ge=0, le=1) - mandatory_with_default: float = Field(ge=0, le=1, default=0.2) - mandatory_with_none: float = Field(ge=0, le=1, default=None) - optional: t.Optional[float] = Field(ge=0, le=1) - optional_with_default: t.Optional[float] = Field(ge=0, le=1, default=0.2) - optional_with_none: t.Optional[float] = Field(ge=0, le=1, default=None) - - -class AllOptionalSubModel(AllOptionalModel): - pass - - -class InheritedAllOptionalModel(ClassicModel, metaclass=AllOptionalMetaclass): - pass - - -class TestAllOptionalModel: - """ - Test that AllOptionalMetaclass works with base classes. - """ - - @pytest.mark.parametrize("cls", [AllOptionalModel, AllOptionalSubModel, InheritedAllOptionalModel]) - def test_classes(self, cls: t.Type[BaseModel]) -> None: - assert cls.__fields__["mandatory"].required is False - assert cls.__fields__["mandatory"].allow_none is True - assert cls.__fields__["mandatory"].default is None - assert cls.__fields__["mandatory"].default_factory is None # undefined - - assert cls.__fields__["mandatory_with_default"].required is False - assert cls.__fields__["mandatory_with_default"].allow_none is True - assert cls.__fields__["mandatory_with_default"].default == 0.2 - assert cls.__fields__["mandatory_with_default"].default_factory is None # undefined - - assert cls.__fields__["mandatory_with_none"].required is False - assert cls.__fields__["mandatory_with_none"].allow_none is True - assert cls.__fields__["mandatory_with_none"].default is None - assert cls.__fields__["mandatory_with_none"].default_factory is None # undefined - - assert cls.__fields__["optional"].required is False - assert cls.__fields__["optional"].allow_none is True - assert cls.__fields__["optional"].default is None - assert cls.__fields__["optional"].default_factory is None # undefined - - assert cls.__fields__["optional_with_default"].required is False - assert cls.__fields__["optional_with_default"].allow_none is True - assert cls.__fields__["optional_with_default"].default == 0.2 - assert cls.__fields__["optional_with_default"].default_factory is None # undefined - - assert cls.__fields__["optional_with_none"].required is False - assert cls.__fields__["optional_with_none"].allow_none is True - assert cls.__fields__["optional_with_none"].default is None - assert cls.__fields__["optional_with_none"].default_factory is None # undefined - - @pytest.mark.parametrize("cls", [AllOptionalModel, AllOptionalSubModel, InheritedAllOptionalModel]) - def test_initialization(self, cls: t.Type[AllOptionalModel]) -> None: - # We can build a model without providing values. - # The initialized value will be the default value or `None` for optional values. - # Note that the mandatory fields are not required anymore, and can be `None`. - obj = cls() - assert obj.mandatory is None - assert obj.mandatory_with_default == 0.2 - assert obj.mandatory_with_none is None - assert obj.optional is None - assert obj.optional_with_default == 0.2 - assert obj.optional_with_none is None - - # If we convert the model to a dictionary, without `None` values, - # we should have a dictionary with default values only. - actual = obj.dict(exclude_none=True) - expected = { - "mandatory_with_default": 0.2, - "optional_with_default": 0.2, - } - assert actual == expected - - @pytest.mark.parametrize("cls", [AllOptionalModel, AllOptionalSubModel, InheritedAllOptionalModel]) - def test_validation(self, cls: t.Type[AllOptionalModel]) -> None: - # We can use `None` as a value for all fields. - cls(mandatory=None) - cls(mandatory_with_default=None) - cls(mandatory_with_none=None) - cls(optional=None) - cls(optional_with_default=None) - cls(optional_with_none=None) - - # We can validate a model with valid values. - cls( - mandatory=0.5, - mandatory_with_default=0.2, - mandatory_with_none=0.2, - optional=0.5, - optional_with_default=0.2, - optional_with_none=0.2, - ) - - # We CANNOT validate a model with invalid values. - with pytest.raises(ValidationError): - cls(mandatory=2) - - with pytest.raises(ValidationError): - cls(mandatory_with_default=2) - - with pytest.raises(ValidationError): - cls(mandatory_with_none=2) - - with pytest.raises(ValidationError): - cls(optional=2) - - with pytest.raises(ValidationError): - cls(optional_with_default=2) - - with pytest.raises(ValidationError): - cls(optional_with_none=2) - - -# The `use_none` keyword argument is set to `True` to allow the use of `None` -# as a default value for the fields of the model. - - -class UseNoneModel(BaseModel, metaclass=AllOptionalMetaclass, use_none=True): - mandatory: float = Field(ge=0, le=1) - mandatory_with_default: float = Field(ge=0, le=1, default=0.2) - mandatory_with_none: float = Field(ge=0, le=1, default=None) - optional: t.Optional[float] = Field(ge=0, le=1) - optional_with_default: t.Optional[float] = Field(ge=0, le=1, default=0.2) - optional_with_none: t.Optional[float] = Field(ge=0, le=1, default=None) - - -class UseNoneSubModel(UseNoneModel): +@all_optional_model +class OptionalModel(Model): pass -class InheritedUseNoneModel(ClassicModel, metaclass=AllOptionalMetaclass, use_none=True): +@all_optional_model +@camel_case_model +class OptionalCamelCaseModel(Model): pass -class TestUseNoneModel: - @pytest.mark.parametrize("cls", [UseNoneModel, UseNoneSubModel, InheritedUseNoneModel]) - def test_classes(self, cls: t.Type[BaseModel]) -> None: - assert cls.__fields__["mandatory"].required is False - assert cls.__fields__["mandatory"].allow_none is True - assert cls.__fields__["mandatory"].default is None - assert cls.__fields__["mandatory"].default_factory is None # undefined - - assert cls.__fields__["mandatory_with_default"].required is False - assert cls.__fields__["mandatory_with_default"].allow_none is True - assert cls.__fields__["mandatory_with_default"].default is None - assert cls.__fields__["mandatory_with_default"].default_factory is None # undefined - - assert cls.__fields__["mandatory_with_none"].required is False - assert cls.__fields__["mandatory_with_none"].allow_none is True - assert cls.__fields__["mandatory_with_none"].default is None - assert cls.__fields__["mandatory_with_none"].default_factory is None # undefined - - assert cls.__fields__["optional"].required is False - assert cls.__fields__["optional"].allow_none is True - assert cls.__fields__["optional"].default is None - assert cls.__fields__["optional"].default_factory is None # undefined - - assert cls.__fields__["optional_with_default"].required is False - assert cls.__fields__["optional_with_default"].allow_none is True - assert cls.__fields__["optional_with_default"].default is None - assert cls.__fields__["optional_with_default"].default_factory is None # undefined - - assert cls.__fields__["optional_with_none"].required is False - assert cls.__fields__["optional_with_none"].allow_none is True - assert cls.__fields__["optional_with_none"].default is None - assert cls.__fields__["optional_with_none"].default_factory is None # undefined - - @pytest.mark.parametrize("cls", [UseNoneModel, UseNoneSubModel, InheritedUseNoneModel]) - def test_initialization(self, cls: t.Type[UseNoneModel]) -> None: - # We can build a model without providing values. - # The initialized value will be the default value or `None` for optional values. - # Note that the mandatory fields are not required anymore, and can be `None`. - obj = cls() - assert obj.mandatory is None - assert obj.mandatory_with_default is None - assert obj.mandatory_with_none is None - assert obj.optional is None - assert obj.optional_with_default is None - assert obj.optional_with_none is None - - # If we convert the model to a dictionary, without `None` values, - # we should have an empty dictionary. - actual = obj.dict(exclude_none=True) - expected = {} - assert actual == expected - - @pytest.mark.parametrize("cls", [UseNoneModel, UseNoneSubModel, InheritedUseNoneModel]) - def test_validation(self, cls: t.Type[UseNoneModel]) -> None: - # We can use `None` as a value for all fields. - cls(mandatory=None) - cls(mandatory_with_default=None) - cls(mandatory_with_none=None) - cls(optional=None) - cls(optional_with_default=None) - cls(optional_with_none=None) - - # We can validate a model with valid values. - cls( - mandatory=0.5, - mandatory_with_default=0.2, - mandatory_with_none=0.2, - optional=0.5, - optional_with_default=0.2, - optional_with_none=0.2, - ) - - # We CANNOT validate a model with invalid values. - with pytest.raises(ValidationError): - cls(mandatory=2) - - with pytest.raises(ValidationError): - cls(mandatory_with_default=2) - - with pytest.raises(ValidationError): - cls(mandatory_with_none=2) - - with pytest.raises(ValidationError): - cls(optional=2) - - with pytest.raises(ValidationError): - cls(optional_with_default=2) - - with pytest.raises(ValidationError): - cls(optional_with_none=2) +def test_model() -> None: + optional_model = OptionalModel() + assert optional_model.float_with_default is None + assert optional_model.float_without_default is None + assert optional_model.boolean_with_default is None + assert optional_model.boolean_without_default is None + assert optional_model.field_with_alias is None + + optional_model = OptionalModel(boolean_with_default=False) + assert optional_model.float_with_default is None + assert optional_model.float_without_default is None + assert optional_model.boolean_with_default is False + assert optional_model.boolean_without_default is None + assert optional_model.field_with_alias is None + + # build with alias should succeed + args = {"field-with-alias": "test"} + optional_model = OptionalModel(**args) + assert optional_model.field_with_alias == "test" + + # build with camel_case should succeed + args = {"fieldWithAlias": "test"} + camel_case_model = OptionalCamelCaseModel(**args) + assert camel_case_model.field_with_alias == "test" diff --git a/tests/study/business/test_allocation_manager.py b/tests/study/business/test_allocation_manager.py index 82f49b2ec4..a7fec22f2e 100644 --- a/tests/study/business/test_allocation_manager.py +++ b/tests/study/business/test_allocation_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import re import uuid @@ -35,7 +47,7 @@ def test_base(self): def test_camel_case(self): field = AllocationField(areaId="NORTH", coefficient=1) - assert field.dict(by_alias=True) == { + assert field.model_dump(by_alias=True) == { "areaId": "NORTH", "coefficient": 1, } diff --git a/tests/study/business/test_binding_constraint_management.py b/tests/study/business/test_binding_constraint_management.py index 17bf1628ec..dcec736496 100644 --- a/tests/study/business/test_binding_constraint_management.py +++ b/tests/study/business/test_binding_constraint_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import typing as t import pytest diff --git a/tests/study/business/test_correlation_manager.py b/tests/study/business/test_correlation_manager.py index e772b2f27f..56d66c9e47 100644 --- a/tests/study/business/test_correlation_manager.py +++ b/tests/study/business/test_correlation_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import uuid from unittest.mock import Mock, patch diff --git a/tests/study/business/test_district_manager.py b/tests/study/business/test_district_manager.py index 5411145882..51c040302d 100644 --- a/tests/study/business/test_district_manager.py +++ b/tests/study/business/test_district_manager.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock, patch import pytest diff --git a/tests/study/business/test_matrix_management.py b/tests/study/business/test_matrix_management.py index c52f84b411..11bf3dfd2b 100644 --- a/tests/study/business/test_matrix_management.py +++ b/tests/study/business/test_matrix_management.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from typing import List, Tuple import pandas as pd diff --git a/tests/study/storage/__init__.py b/tests/study/storage/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/storage/__init__.py +++ b/tests/study/storage/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/storage/rawstudy/__init__.py b/tests/study/storage/rawstudy/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/storage/rawstudy/__init__.py +++ b/tests/study/storage/rawstudy/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/storage/rawstudy/test_raw_study_service.py b/tests/study/storage/rawstudy/test_raw_study_service.py index bc09fc0a3f..acf6557bd4 100644 --- a/tests/study/storage/rawstudy/test_raw_study_service.py +++ b/tests/study/storage/rawstudy/test_raw_study_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import typing as t import zipfile diff --git a/tests/study/storage/test_abstract_storage_service.py b/tests/study/storage/test_abstract_storage_service.py index 09d82ea083..97793c206d 100644 --- a/tests/study/storage/test_abstract_storage_service.py +++ b/tests/study/storage/test_abstract_storage_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import zipfile from pathlib import Path diff --git a/tests/study/storage/variantstudy/__init__.py b/tests/study/storage/variantstudy/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/storage/variantstudy/__init__.py +++ b/tests/study/storage/variantstudy/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/storage/variantstudy/business/__init__.py b/tests/study/storage/variantstudy/business/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/storage/variantstudy/business/__init__.py +++ b/tests/study/storage/variantstudy/business/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py b/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py index da5ebd91d6..f47bc75a8b 100644 --- a/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py +++ b/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy as np from antarest.matrixstore.repository import MatrixContentRepository diff --git a/tests/study/storage/variantstudy/model/__init__.py b/tests/study/storage/variantstudy/model/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/study/storage/variantstudy/model/__init__.py +++ b/tests/study/storage/variantstudy/model/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/study/storage/variantstudy/model/test_dbmodel.py b/tests/study/storage/variantstudy/model/test_dbmodel.py index 6ed1bbcba1..aff5686dcb 100644 --- a/tests/study/storage/variantstudy/model/test_dbmodel.py +++ b/tests/study/storage/variantstudy/model/test_dbmodel.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import json import typing as t @@ -152,7 +164,7 @@ def test_init(self, db_session: Session, variant_study_id: str) -> None: # check CommandBlock.to_dto() dto = obj.to_dto() # note: it is easier to compare the dict representation of the DTO - assert dto.dict() == { + assert dto.model_dump() == { "id": command_id, "action": command, "args": json.loads(args), diff --git a/tests/study/storage/variantstudy/test_snapshot_generator.py b/tests/study/storage/variantstudy/test_snapshot_generator.py index e9de3da131..0f2d4775ef 100644 --- a/tests/study/storage/variantstudy/test_snapshot_generator.py +++ b/tests/study/storage/variantstudy/test_snapshot_generator.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import configparser import datetime import json @@ -851,7 +863,7 @@ def test_generate__nominal_case( assert len(db_recorder.sql_statements) == 5, str(db_recorder) # Check: the variant generation must succeed. - assert results.dict() == { + assert results.model_dump() == { "success": True, "details": [ { @@ -1036,7 +1048,7 @@ def test_generate__with_denormalize_true( ) # Check the results - assert results.dict() == { + assert results.model_dump() == { "success": True, "details": [ { @@ -1159,7 +1171,7 @@ def test_generate__notification_failure( ) # Check the results - assert results.dict() == { + assert results.model_dump() == { "success": True, "details": [ { @@ -1241,7 +1253,7 @@ def test_generate__variant_of_variant( ) # Check the results - assert results.dict() == { + assert results.model_dump() == { "success": True, "details": [ { diff --git a/tests/study/storage/variantstudy/test_variant_study_service.py b/tests/study/storage/variantstudy/test_variant_study_service.py index 9dce83e735..cd8f9100c0 100644 --- a/tests/study/storage/variantstudy/test_variant_study_service.py +++ b/tests/study/storage/variantstudy/test_variant_study_service.py @@ -1,15 +1,30 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import re +import typing from pathlib import Path from unittest.mock import Mock import numpy as np import pytest +from antarest.core.jwt import DEFAULT_ADMIN_USER, JWTUser from antarest.core.model import PublicMode -from antarest.core.requests import RequestParameters +from antarest.core.requests import RequestParameters, UserHasNotPermissionError from antarest.core.utils.fastapi_sqlalchemy import db -from antarest.login.model import Group, User +from antarest.core.utils.utils import sanitize_uuid +from antarest.login.model import ADMIN_ID, ADMIN_NAME, Group, User from antarest.matrixstore.service import SimpleMatrixService from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import RawStudy, StudyAdditionalData @@ -227,3 +242,188 @@ def test_generate_task( else: expected = EXPECTED_DENORMALIZED assert res_study_files == expected + + @with_db_context + def test_clear_all_snapshots( + self, + tmp_path: Path, + variant_study_service: VariantStudyService, + raw_study_service: RawStudyService, + monkeypatch: pytest.MonkeyPatch, + ) -> None: + """ + - Test return value in case the user is not allowed to call the function, + - Test return value in case the user give a bad argument (negative + integer or other type than integer) + - Test deletion of an old snapshot and a recent one + + In order to test date and time of objects, a FakeDateTime class is defined and used + by a monkeypatch context + """ + + class FakeDatetime: + """ + Class that handle fake timestamp creation/update of variant + """ + + fake_time: datetime.datetime + + @classmethod + def now(cls) -> datetime.datetime: + """Method used to get the custom timestamp""" + return datetime.datetime(2023, 12, 31) + + @classmethod + def utcnow(cls) -> datetime.datetime: + """Method used while a variant is created""" + return cls.now() + + # ============================= + # SET UP + # ============================= + # Create two users + # an admin user + # noinspection PyArgumentList + admin_user = User(id=ADMIN_ID, name=ADMIN_NAME) + db.session.add(admin_user) + db.session.commit() + + regular_user = User(id=99, name="regular") + db.session.add(regular_user) + db.session.commit() + + # noinspection PyArgumentList + group = Group(id="my-group", name="group") + db.session.add(group) + db.session.commit() + + # Create a raw study (root of the variant) + raw_study_path = tmp_path / "My RAW Study" + # noinspection PyArgumentList + raw_study = RawStudy( + id="my_raw_study", + name=raw_study_path.name, + version="860", + author="John Smith", + created_at=datetime.datetime(2023, 7, 15, 16, 45), + updated_at=datetime.datetime(2023, 7, 19, 8, 15), + last_access=datetime.datetime.utcnow(), + public_mode=PublicMode.FULL, + owner=admin_user, + groups=[group], + path=str(raw_study_path), + additional_data=StudyAdditionalData(author="John Smith"), + ) + + db.session.add(raw_study) + db.session.commit() + + # Set up the Raw Study + raw_study_service.create(raw_study) + + # Variant studies + variant_list = [] + + # For each variant created + with monkeypatch.context() as m: + # Set the system date older to create older variants + m.setattr("antarest.study.storage.variantstudy.variant_study_service.datetime", FakeDatetime) + m.setattr("antarest.study.service.datetime", FakeDatetime) + + for index in range(3): + variant_list.append( + variant_study_service.create_variant_study( + raw_study.id, + "Variant{}".format(str(index)), + params=Mock( + spec=RequestParameters, + user=DEFAULT_ADMIN_USER, + ), + ) + ) + + # Generate a snapshot for each variant + variant_study_service.generate( + sanitize_uuid(variant_list[index].id), + False, + False, + params=Mock( + spec=RequestParameters, + user=Mock(spec=JWTUser, id=regular_user.id, impersonator=regular_user.id), + ), + ) + + variant_study_service.get(variant_list[index]) + + variant_study_path = Path(tmp_path).joinpath("internal_studies") + + # Check if everything was correctly initialized + assert len(list(variant_study_path.iterdir())) == 3 + + for variant in variant_study_path.iterdir(): + assert variant.is_dir() + assert list(variant.iterdir())[0].name == "snapshot" + + # ============================= + # TEST + # ============================= + # A user without rights cannot clear snapshots + with pytest.raises(UserHasNotPermissionError): + variant_study_service.clear_all_snapshots( + datetime.timedelta(1), + params=Mock( + spec=RequestParameters, + user=Mock( + spec=JWTUser, + id=regular_user.id, + is_site_admin=Mock(return_value=False), + is_admin_token=Mock(return_value=False), + ), + ), + ) + + # At this point, variants was not accessed yet + # Thus snapshot directories must exist still + for variant in variant_study_path.iterdir(): + assert variant.is_dir() + assert list(variant.iterdir()) + + # Simulate access for two old snapshots + variant_list[0].last_access = datetime.datetime.utcnow() - datetime.timedelta(days=60) + variant_list[1].last_access = datetime.datetime.utcnow() - datetime.timedelta(hours=6) + + # Simulate access for a recent one + variant_list[2].last_access = datetime.datetime.utcnow() - datetime.timedelta(hours=1) + db.session.commit() + + # Clear old snapshots + task_id = variant_study_service.clear_all_snapshots( + datetime.timedelta(hours=5), + Mock( + spec=RequestParameters, + user=DEFAULT_ADMIN_USER, + ), + ) + variant_study_service.task_service.await_task(task_id) + + # Check if old snapshots was successfully cleared + nb_snapshot_dir = 0 # after the for iterations, must equal 1 + for variant_path in variant_study_path.iterdir(): + if variant_path.joinpath("snapshot").exists(): + nb_snapshot_dir += 1 + assert nb_snapshot_dir == 1 + + # Clear most recent snapshots + task_id = variant_study_service.clear_all_snapshots( + datetime.timedelta(hours=-1), + Mock( + spec=RequestParameters, + user=DEFAULT_ADMIN_USER, + ), + ) + variant_study_service.task_service.await_task(task_id) + + # Check if all snapshots were cleared + nb_snapshot_dir = 0 # after the for iterations, must equal 0 + for variant_path in variant_study_path.iterdir(): + assert not variant_path.joinpath("snapshot").exists() diff --git a/tests/study/test_model.py b/tests/study/test_model.py index 04785a28df..c93bdacc49 100644 --- a/tests/study/test_model.py +++ b/tests/study/test_model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + """ Test the database model. """ diff --git a/tests/study/test_repository.py b/tests/study/test_repository.py index f7314cdaaa..bcdcea759b 100644 --- a/tests/study/test_repository.py +++ b/tests/study/test_repository.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import typing as t from unittest.mock import Mock @@ -905,9 +917,9 @@ def test_get_all__non_admin_permissions_filter( user_2 = User(id=102, name="user2") user_3 = User(id=103, name="user3") - group_1 = Group(id=101, name="group1") - group_2 = Group(id=102, name="group2") - group_3 = Group(id=103, name="group3") + group_1 = Group(id="101", name="group1") + group_2 = Group(id="102", name="group2") + group_3 = Group(id="103", name="group3") user_groups_mapping = {101: [group_2.id], 102: [group_1.id], 103: []} @@ -1179,23 +1191,23 @@ def test_update_tags( (None, [], False, ["5", "6"]), (None, [], True, ["1", "2", "3", "4", "7", "8"]), (None, [], None, ["1", "2", "3", "4", "5", "6", "7", "8"]), - (None, [1, 3, 5, 7], False, ["5"]), - (None, [1, 3, 5, 7], True, ["1", "3", "7"]), - (None, [1, 3, 5, 7], None, ["1", "3", "5", "7"]), + (None, ["1", "3", "5", "7"], False, ["5"]), + (None, ["1", "3", "5", "7"], True, ["1", "3", "7"]), + (None, ["1", "3", "5", "7"], None, ["1", "3", "5", "7"]), (True, [], False, ["5"]), (True, [], True, ["1", "2", "3", "4", "8"]), (True, [], None, ["1", "2", "3", "4", "5", "8"]), - (True, [1, 3, 5, 7], False, ["5"]), - (True, [1, 3, 5, 7], True, ["1", "3"]), - (True, [1, 3, 5, 7], None, ["1", "3", "5"]), - (True, [2, 4, 6, 8], True, ["2", "4", "8"]), - (True, [2, 4, 6, 8], None, ["2", "4", "8"]), + (True, ["1", "3", "5", "7"], False, ["5"]), + (True, ["1", "3", "5", "7"], True, ["1", "3"]), + (True, ["1", "3", "5", "7"], None, ["1", "3", "5"]), + (True, ["2", "4", "6", "8"], True, ["2", "4", "8"]), + (True, ["2", "4", "6", "8"], None, ["2", "4", "8"]), (False, [], False, ["6"]), (False, [], True, ["7"]), (False, [], None, ["6", "7"]), - (False, [1, 3, 5, 7], False, []), - (False, [1, 3, 5, 7], True, ["7"]), - (False, [1, 3, 5, 7], None, ["7"]), + (False, ["1", "3", "5", "7"], False, []), + (False, ["1", "3", "5", "7"], True, ["7"]), + (False, ["1", "3", "5", "7"], None, ["7"]), ], ) def test_count_studies__general_case( @@ -1209,14 +1221,14 @@ def test_count_studies__general_case( icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1, name="study-1") - study_2 = VariantStudy(id=2, name="study-2") - study_3 = VariantStudy(id=3, name="study-3") - study_4 = VariantStudy(id=4, name="study-4") - study_5 = RawStudy(id=5, name="study-5", missing=datetime.datetime.now(), workspace=DEFAULT_WORKSPACE_NAME) - study_6 = RawStudy(id=6, name="study-6", missing=datetime.datetime.now(), workspace=test_workspace) - study_7 = RawStudy(id=7, name="study-7", missing=None, workspace=test_workspace) - study_8 = RawStudy(id=8, name="study-8", missing=None, workspace=DEFAULT_WORKSPACE_NAME) + study_1 = VariantStudy(id="1", name="study-1") + study_2 = VariantStudy(id="2", name="study-2") + study_3 = VariantStudy(id="3", name="study-3") + study_4 = VariantStudy(id="4", name="study-4") + study_5 = RawStudy(id="5", name="study-5", missing=datetime.datetime.now(), workspace=DEFAULT_WORKSPACE_NAME) + study_6 = RawStudy(id="6", name="study-6", missing=datetime.datetime.now(), workspace=test_workspace) + study_7 = RawStudy(id="7", name="study-7", missing=None, workspace=test_workspace) + study_8 = RawStudy(id="8", name="study-8", missing=None, workspace=DEFAULT_WORKSPACE_NAME) db_session.add_all([study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8]) db_session.commit() diff --git a/tests/study/test_service.py b/tests/study/test_service.py index 274525021f..8192104209 100644 --- a/tests/study/test_service.py +++ b/tests/study/test_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path import pytest diff --git a/tests/test_front.py b/tests/test_front.py new file mode 100644 index 0000000000..5046a868cf --- /dev/null +++ b/tests/test_front.py @@ -0,0 +1,111 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + +from pathlib import Path + +import pytest +from fastapi import FastAPI +from starlette.testclient import TestClient + +from antarest.front import RedirectMiddleware, add_front_app + + +@pytest.fixture +def base_back_app() -> FastAPI: + """ + A simple app which has only one backend endpoint + """ + app = FastAPI(title=__name__) + + @app.get(path="/api/a-backend-endpoint") + def get_from_api() -> str: + return "back" + + return app + + +@pytest.fixture +def resources_dir(tmp_path: Path) -> Path: + resource_dir = tmp_path / "resources" + resource_dir.mkdir() + webapp_dir = resource_dir / "webapp" + webapp_dir.mkdir() + with open(webapp_dir / "index.html", mode="w") as f: + f.write("index") + with open(webapp_dir / "front.css", mode="w") as f: + f.write("css") + return resource_dir + + +@pytest.fixture +def app_with_home(base_back_app) -> FastAPI: + """ + A simple app which has only a home endpoint and one backend endpoint + """ + + @base_back_app.get(path="/") + def home() -> str: + return "home" + + return base_back_app + + +@pytest.fixture +def redirect_app(app_with_home: FastAPI) -> FastAPI: + """ + Same as app with redirect middleware + """ + route_paths = [r.path for r in app_with_home.routes] # type: ignore + app_with_home.add_middleware(RedirectMiddleware, route_paths=route_paths) + return app_with_home + + +def test_redirect_middleware_does_not_modify_home(redirect_app: FastAPI) -> None: + client = TestClient(redirect_app) + response = client.get("/") + assert response.status_code == 200 + assert response.json() == "home" + + +def test_redirect_middleware_redirects_unknown_routes_to_home(redirect_app: FastAPI) -> None: + client = TestClient(redirect_app) + response = client.get("/a-front-route") + assert response.status_code == 200 + assert response.json() == "home" + + +def test_redirect_middleware_does_not_redirect_backend_routes(redirect_app: FastAPI) -> None: + client = TestClient(redirect_app) + response = client.get("/api/a-backend-endpoint") + assert response.status_code == 200 + assert response.json() == "back" + + +def test_frontend_paths(base_back_app, resources_dir: Path) -> None: + add_front_app(base_back_app, resources_dir, "/api") + client = TestClient(base_back_app) + + config_response = client.get("/config.json") + assert config_response.status_code == 200 + assert config_response.json() == {"restEndpoint": "/api", "wsEndpoint": "/api/ws"} + + index_response = client.get("/index.html") + assert index_response.status_code == 200 + assert index_response.text == "index" + + front_route_response = client.get("/any-route") + assert front_route_response.status_code == 200 + assert front_route_response.text == "index" + + front_static_file_response = client.get("/static/front.css") + assert front_static_file_response.status_code == 200 + assert front_static_file_response.text == "css" diff --git a/tests/test_resources.py b/tests/test_resources.py index 330116e507..8c9abf46a6 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import pathlib import zipfile from typing import Sequence diff --git a/tests/variantstudy/__init__.py b/tests/variantstudy/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/variantstudy/__init__.py +++ b/tests/variantstudy/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/variantstudy/assets/__init__.py b/tests/variantstudy/assets/__init__.py index 773f16ec60..3fff24b6fe 100644 --- a/tests/variantstudy/assets/__init__.py +++ b/tests/variantstudy/assets/__init__.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path ASSETS_DIR = Path(__file__).parent.resolve() diff --git a/tests/variantstudy/conftest.py b/tests/variantstudy/conftest.py index 5d10267bbd..beaaf34065 100644 --- a/tests/variantstudy/conftest.py +++ b/tests/variantstudy/conftest.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import hashlib import re import typing as t diff --git a/tests/variantstudy/model/__init__.py b/tests/variantstudy/model/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/variantstudy/model/__init__.py +++ b/tests/variantstudy/model/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/variantstudy/model/command/__init__.py b/tests/variantstudy/model/command/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/variantstudy/model/command/__init__.py +++ b/tests/variantstudy/model/command/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/variantstudy/model/command/helpers.py b/tests/variantstudy/model/command/helpers.py index d2dfd55c1e..4e6a792c61 100644 --- a/tests/variantstudy/model/command/helpers.py +++ b/tests/variantstudy/model/command/helpers.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path diff --git a/tests/variantstudy/model/command/test_alias_decoder.py b/tests/variantstudy/model/command/test_alias_decoder.py index f295301dd1..193c13a151 100644 --- a/tests/variantstudy/model/command/test_alias_decoder.py +++ b/tests/variantstudy/model/command/test_alias_decoder.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock, patch import pytest diff --git a/tests/variantstudy/model/command/test_create_area.py b/tests/variantstudy/model/command/test_create_area.py index 2036b12b93..0bb8c104c7 100644 --- a/tests/variantstudy/model/command/test_create_area.py +++ b/tests/variantstudy/model/command/test_create_area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import configparser from unittest.mock import Mock diff --git a/tests/variantstudy/model/command/test_create_cluster.py b/tests/variantstudy/model/command/test_create_cluster.py index 6554bbe6c2..35c21e91ab 100644 --- a/tests/variantstudy/model/command/test_create_cluster.py +++ b/tests/variantstudy/model/command/test_create_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import configparser import re @@ -16,11 +28,13 @@ from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig from antarest.study.storage.variantstudy.model.command_context import CommandContext +GEN = np.random.default_rng(1000) + class TestCreateCluster: def test_init(self, command_context: CommandContext): - prepro = np.random.rand(365, 6).tolist() - modulation = np.random.rand(8760, 4).tolist() + prepro = GEN.random((365, 6)).tolist() + modulation = GEN.random((8760, 4)).tolist() cl = CreateCluster( area_id="foo", cluster_name="Cluster1", @@ -40,7 +54,7 @@ def test_init(self, command_context: CommandContext): modulation_id = command_context.matrix_service.create(modulation) assert cl.area_id == "foo" assert cl.cluster_name == "Cluster1" - assert cl.parameters == {"group": "Nuclear", "nominalcapacity": "2400", "unitcount": "2"} + assert cl.parameters == {"group": "Nuclear", "nominalcapacity": 2400, "unitcount": 2} assert cl.prepro == f"matrix://{prepro_id}" assert cl.modulation == f"matrix://{modulation_id}" @@ -73,8 +87,8 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): "market-bid-cost": "30", } - prepro = np.random.rand(365, 6).tolist() - modulation = np.random.rand(8760, 4).tolist() + prepro = GEN.random((365, 6)).tolist() + modulation = GEN.random((8760, 4)).tolist() command = CreateCluster( area_id=area_id, cluster_name=cluster_name, @@ -135,8 +149,8 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): ) def test_to_dto(self, command_context: CommandContext): - prepro = np.random.rand(365, 6).tolist() - modulation = np.random.rand(8760, 4).tolist() + prepro = GEN.random((365, 6)).tolist() + modulation = GEN.random((8760, 4)).tolist() command = CreateCluster( area_id="foo", cluster_name="Cluster1", @@ -148,12 +162,12 @@ def test_to_dto(self, command_context: CommandContext): prepro_id = command_context.matrix_service.create(prepro) modulation_id = command_context.matrix_service.create(modulation) dto = command.to_dto() - assert dto.dict() == { + assert dto.model_dump() == { "action": "create_cluster", "args": { "area_id": "foo", "cluster_name": "Cluster1", - "parameters": {"group": "Nuclear", "nominalcapacity": "2400", "unitcount": "2"}, + "parameters": {"group": "Nuclear", "nominalcapacity": 2400, "unitcount": 2}, "prepro": prepro_id, "modulation": modulation_id, }, @@ -163,8 +177,8 @@ def test_to_dto(self, command_context: CommandContext): def test_match(command_context: CommandContext): - prepro = np.random.rand(365, 6).tolist() - modulation = np.random.rand(8760, 4).tolist() + prepro = GEN.random((365, 6)).tolist() + modulation = GEN.random((8760, 4)).tolist() base = CreateCluster( area_id="foo", cluster_name="foo", @@ -223,8 +237,8 @@ def test_revert(command_context: CommandContext): def test_create_diff(command_context: CommandContext): - prepro_a = np.random.rand(365, 6).tolist() - modulation_a = np.random.rand(8760, 4).tolist() + prepro_a = GEN.random((365, 6)).tolist() + modulation_a = GEN.random((8760, 4)).tolist() base = CreateCluster( area_id="foo", cluster_name="foo", @@ -234,8 +248,8 @@ def test_create_diff(command_context: CommandContext): command_context=command_context, ) - prepro_b = np.random.rand(365, 6).tolist() - modulation_b = np.random.rand(8760, 4).tolist() + prepro_b = GEN.random((365, 6)).tolist() + modulation_b = GEN.random((8760, 4)).tolist() other_match = CreateCluster( area_id="foo", cluster_name="foo", diff --git a/tests/variantstudy/model/command/test_create_link.py b/tests/variantstudy/model/command/test_create_link.py index eb11d65398..9d847f0f24 100644 --- a/tests/variantstudy/model/command/test_create_link.py +++ b/tests/variantstudy/model/command/test_create_link.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import configparser import numpy as np @@ -25,16 +37,15 @@ def test_validation(self, empty_study: FileStudy, command_context: CommandContex area1_id = transform_name_to_id(area1) area2 = "Area2" - area2_id = transform_name_to_id(area2) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area1, "command_context": command_context, } ).apply(empty_study) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area2, "command_context": command_context, @@ -42,7 +53,7 @@ def test_validation(self, empty_study: FileStudy, command_context: CommandContex ).apply(empty_study) with pytest.raises(ValidationError): - create_link_command: ICommand = CreateLink( + CreateLink( area1=area1_id, area2=area1_id, parameters={}, @@ -61,21 +72,21 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): area3 = "Area3" area3_id = transform_name_to_id(area3) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area1, "command_context": command_context, } ).apply(empty_study) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area2, "command_context": command_context, } ).apply(empty_study) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area3, "command_context": command_context, @@ -133,7 +144,7 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): # TODO:assert matrix default content : 1 column, 8760 rows, value = 1 - output = CreateLink.parse_obj( + output = CreateLink.model_validate( { "area1": area1_id, "area2": area2_id, @@ -161,7 +172,7 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): "filter-year-by-year": "hourly", } - create_link_command: ICommand = CreateLink.parse_obj( + create_link_command: ICommand = CreateLink.model_validate( { "area1": area3_id, "area2": area1_id, diff --git a/tests/variantstudy/model/command/test_create_renewables_cluster.py b/tests/variantstudy/model/command/test_create_renewables_cluster.py index 78e6dcf15e..b23d6ba553 100644 --- a/tests/variantstudy/model/command/test_create_renewables_cluster.py +++ b/tests/variantstudy/model/command/test_create_renewables_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import configparser import re from unittest import mock @@ -34,7 +46,7 @@ def test_init(self, command_context: CommandContext) -> None: # Check the command data assert cl.area_id == "foo" assert cl.cluster_name == "Cluster1" - assert cl.parameters == {"group": "Solar Thermal", "nominalcapacity": "2400", "unitcount": "2"} + assert cl.parameters == {"group": "Solar Thermal", "nominalcapacity": 2400, "unitcount": 2} def test_validate_cluster_name(self, command_context: CommandContext) -> None: with pytest.raises(ValidationError, match="cluster_name"): @@ -119,12 +131,12 @@ def test_to_dto(self, command_context: CommandContext) -> None: command_context=command_context, ) dto = command.to_dto() - assert dto.dict() == { + assert dto.model_dump() == { "action": "create_renewables_cluster", # "renewables" with a final "s". "args": { "area_id": "foo", "cluster_name": "Cluster1", - "parameters": {"group": "Solar Thermal", "nominalcapacity": "2400", "unitcount": "2"}, + "parameters": {"group": "Solar Thermal", "nominalcapacity": 2400, "unitcount": 2}, }, "id": None, "version": 1, diff --git a/tests/variantstudy/model/command/test_create_st_storage.py b/tests/variantstudy/model/command/test_create_st_storage.py index 7e2a7fa7b5..14fbef9b8b 100644 --- a/tests/variantstudy/model/command/test_create_st_storage.py +++ b/tests/variantstudy/model/command/test_create_st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import numpy as np @@ -17,6 +29,8 @@ from antarest.study.storage.variantstudy.model.command_context import CommandContext from antarest.study.storage.variantstudy.model.model import CommandDTO +GEN = np.random.default_rng(1000) + @pytest.fixture(name="recent_study") def recent_study_fixture(empty_study: FileStudy) -> FileStudy: @@ -63,8 +77,8 @@ def recent_study_fixture(empty_study: FileStudy) -> FileStudy: class TestCreateSTStorage: # noinspection SpellCheckingInspection def test_init(self, command_context: CommandContext): - pmax_injection = np.random.rand(8760, 1) - inflows = np.random.uniform(0, 1000, size=(8760, 1)) + pmax_injection = GEN.random((8760, 1)) + inflows = GEN.uniform(0, 1000, size=(8760, 1)) cmd = CreateSTStorage( command_context=command_context, area_id="area_fr", @@ -100,17 +114,22 @@ def test_init__invalid_storage_name(self, recent_study: FileStudy, command_conte parameters=STStorageConfig(**parameters), ) # We get 2 errors because the `storage_name` is duplicated in the `parameters`: - assert ctx.value.errors() == [ - { - "loc": ("__root__",), - "msg": "Invalid name '?%$$'.", - "type": "value_error", - } - ] + assert ctx.value.error_count() == 1 + raised_error = ctx.value.errors()[0] + assert raised_error["type"] == "value_error" + assert raised_error["msg"] == "Value error, Invalid name '?%$$'." + assert raised_error["input"] == { + "efficiency": 0.94, + "group": "Battery", + "initialleveloptim": True, + "injectionnominalcapacity": 1500, + "name": "?%$$", + "reservoircapacity": 20000, + "withdrawalnominalcapacity": 1500, + } - # noinspection SpellCheckingInspection def test_init__invalid_matrix_values(self, command_context: CommandContext): - array = np.random.rand(8760, 1) # OK + array = GEN.random((8760, 1)) array[10] = 25 # BAD with pytest.raises(ValidationError) as ctx: CreateSTStorage( @@ -119,17 +138,15 @@ def test_init__invalid_matrix_values(self, command_context: CommandContext): parameters=STStorageConfig(**PARAMETERS), pmax_injection=array.tolist(), # type: ignore ) - assert ctx.value.errors() == [ - { - "loc": ("pmax_injection",), - "msg": "Matrix values should be between 0 and 1", - "type": "value_error", - } - ] + assert ctx.value.error_count() == 1 + raised_error = ctx.value.errors()[0] + assert raised_error["type"] == "value_error" + assert raised_error["msg"] == "Value error, Matrix values should be between 0 and 1" + assert "pmax_injection" in raised_error["input"] # noinspection SpellCheckingInspection def test_init__invalid_matrix_shape(self, command_context: CommandContext): - array = np.random.rand(24, 1) # BAD SHAPE + array = GEN.random((24, 1)) # BAD SHAPE with pytest.raises(ValidationError) as ctx: CreateSTStorage( command_context=command_context, @@ -137,18 +154,14 @@ def test_init__invalid_matrix_shape(self, command_context: CommandContext): parameters=STStorageConfig(**PARAMETERS), pmax_injection=array.tolist(), # type: ignore ) - assert ctx.value.errors() == [ - { - "loc": ("pmax_injection",), - "msg": "Invalid matrix shape (24, 1), expected (8760, 1)", - "type": "value_error", - } - ] - - # noinspection SpellCheckingInspection + assert ctx.value.error_count() == 1 + raised_error = ctx.value.errors()[0] + assert raised_error["type"] == "value_error" + assert raised_error["msg"] == "Value error, Invalid matrix shape (24, 1), expected (8760, 1)" + assert "pmax_injection" in raised_error["input"] def test_init__invalid_nan_value(self, command_context: CommandContext): - array = np.random.rand(8760, 1) # OK + array = GEN.random((8760, 1)) # OK array[20] = np.nan # BAD with pytest.raises(ValidationError) as ctx: CreateSTStorage( @@ -157,37 +170,25 @@ def test_init__invalid_nan_value(self, command_context: CommandContext): parameters=STStorageConfig(**PARAMETERS), pmax_injection=array.tolist(), # type: ignore ) - assert ctx.value.errors() == [ - { - "loc": ("pmax_injection",), - "msg": "Matrix values cannot contain NaN", - "type": "value_error", - } - ] - - # noinspection SpellCheckingInspection + assert ctx.value.error_count() == 1 + raised_error = ctx.value.errors()[0] + assert raised_error["type"] == "value_error" + assert raised_error["msg"] == "Value error, Matrix values cannot contain NaN" + assert "pmax_injection" in raised_error["input"] def test_init__invalid_matrix_type(self, command_context: CommandContext): - array = {"data": [1, 2, 3]} with pytest.raises(ValidationError) as ctx: CreateSTStorage( command_context=command_context, area_id="area_fr", parameters=STStorageConfig(**PARAMETERS), - pmax_injection=array, # type: ignore + pmax_injection=[1, 2, 3], ) - assert ctx.value.errors() == [ - { - "loc": ("pmax_injection",), - "msg": "value is not a valid list", - "type": "type_error.list", - }, - { - "loc": ("pmax_injection",), - "msg": "str type expected", - "type": "type_error.str", - }, - ] + assert ctx.value.error_count() == 1 + raised_error = ctx.value.errors()[0] + assert raised_error["type"] == "value_error" + assert raised_error["msg"] == "Value error, Invalid matrix shape (3,), expected (8760, 1)" + assert "pmax_injection" in raised_error["input"] def test_apply_config__invalid_version(self, empty_study: FileStudy, command_context: CommandContext): # Given an old study in version 720 @@ -293,8 +294,8 @@ def test_apply__nominal_case(self, recent_study: FileStudy, command_context: Com create_area.apply(recent_study) # Then, apply the command to create a new ST Storage - pmax_injection = np.random.rand(8760, 1) - inflows = np.random.uniform(0, 1000, size=(8760, 1)) + pmax_injection = GEN.random((8760, 1)) + inflows = GEN.uniform(0, 1000, size=(8760, 1)) cmd = CreateSTStorage( command_context=command_context, area_id=transform_name_to_id(create_area.area_name), @@ -427,8 +428,8 @@ def test_create_diff__not_equals(self, command_context: CommandContext): area_id="area_fr", parameters=STStorageConfig(**PARAMETERS), ) - upper_rule_curve = np.random.rand(8760, 1) - inflows = np.random.uniform(0, 1000, size=(8760, 1)) + upper_rule_curve = GEN.random((8760, 1)) + inflows = GEN.uniform(0, 1000, size=(8760, 1)) other = CreateSTStorage( command_context=command_context, area_id=cmd.area_id, diff --git a/tests/variantstudy/model/command/test_manage_binding_constraints.py b/tests/variantstudy/model/command/test_manage_binding_constraints.py index d4034658e3..c62cdc8e27 100644 --- a/tests/variantstudy/model/command/test_manage_binding_constraints.py +++ b/tests/variantstudy/model/command/test_manage_binding_constraints.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock import numpy as np diff --git a/tests/variantstudy/model/command/test_manage_district.py b/tests/variantstudy/model/command/test_manage_district.py index 78d30bb19f..47b6e55c42 100644 --- a/tests/variantstudy/model/command/test_manage_district.py +++ b/tests/variantstudy/model/command/test_manage_district.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.rawstudy.ini_reader import IniReader from antarest.study.storage.rawstudy.model.filesystem.config.files import build from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id @@ -14,7 +26,6 @@ def test_manage_district(empty_study: FileStudy, command_context: CommandContext): - study_path = empty_study.config.study_path area1 = "Area1" area1_id = transform_name_to_id(area1) @@ -22,23 +33,22 @@ def test_manage_district(empty_study: FileStudy, command_context: CommandContext area2_id = transform_name_to_id(area2) area3 = "Area3" - area3_id = transform_name_to_id(area3) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area1, "command_context": command_context, } ).apply(empty_study) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area2, "command_context": command_context, } ).apply(empty_study) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area3, "command_context": command_context, diff --git a/tests/variantstudy/model/command/test_remove_area.py b/tests/variantstudy/model/command/test_remove_area.py index 8849bffbd3..474ce51a42 100644 --- a/tests/variantstudy/model/command/test_remove_area.py +++ b/tests/variantstudy/model/command/test_remove_area.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import pytest from checksumdir import dirhash @@ -200,7 +212,7 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): if empty_study.config.version >= 810: default_ruleset[f"r,{area_id2},0,{renewable_id.lower()}"] = 1 if empty_study.config.version >= 870: - default_ruleset[f"bc,bd 2,0"] = 1 + default_ruleset["bc,bd 2,0"] = 1 if empty_study.config.version >= 920: default_ruleset[f"hfl,{area_id2},0"] = 1 if empty_study.config.version >= 910: diff --git a/tests/variantstudy/model/command/test_remove_cluster.py b/tests/variantstudy/model/command/test_remove_cluster.py index cb1af2fdab..77f6ec36c2 100644 --- a/tests/variantstudy/model/command/test_remove_cluster.py +++ b/tests/variantstudy/model/command/test_remove_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import numpy as np import pytest from checksumdir import dirhash diff --git a/tests/variantstudy/model/command/test_remove_link.py b/tests/variantstudy/model/command/test_remove_link.py index 2704a54013..e7e46bb6af 100644 --- a/tests/variantstudy/model/command/test_remove_link.py +++ b/tests/variantstudy/model/command/test_remove_link.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os import typing as t import uuid @@ -58,7 +70,7 @@ def test_remove_link__validation(self, area1: str, area2: str, expected: t.Dict[ and that the areas are well-ordered in alphabetical order (Antares Solver convention). """ command = RemoveLink(area1=area1, area2=area2, command_context=Mock(spec=CommandContext)) - actual = command.dict(include={"area1", "area2"}) + actual = command.model_dump(include={"area1", "area2"}) assert actual == expected @staticmethod diff --git a/tests/variantstudy/model/command/test_remove_renewables_cluster.py b/tests/variantstudy/model/command/test_remove_renewables_cluster.py index 447ce2bea6..d0fe02c54e 100644 --- a/tests/variantstudy/model/command/test_remove_renewables_cluster.py +++ b/tests/variantstudy/model/command/test_remove_renewables_cluster.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from checksumdir import dirhash from antarest.study.storage.rawstudy.model.filesystem.config.model import EnrModelling, transform_name_to_id diff --git a/tests/variantstudy/model/command/test_remove_st_storage.py b/tests/variantstudy/model/command/test_remove_st_storage.py index 944f3b57b4..032a303650 100644 --- a/tests/variantstudy/model/command/test_remove_st_storage.py +++ b/tests/variantstudy/model/command/test_remove_st_storage.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import pytest @@ -71,9 +83,11 @@ def test_init__invalid_storage_id(self, recent_study: FileStudy, command_context assert ctx.value.errors() == [ { "ctx": {"pattern": "[a-z0-9_(),& -]+"}, + "input": "?%$$", "loc": ("storage_id",), - "msg": 'string does not match regex "[a-z0-9_(),& -]+"', - "type": "value_error.str.regex", + "msg": "String should match pattern '[a-z0-9_(),& -]+'", + "type": "string_pattern_mismatch", + "url": "https://errors.pydantic.dev/2.8/v/string_pattern_mismatch", } ] diff --git a/tests/variantstudy/model/command/test_replace_matrix.py b/tests/variantstudy/model/command/test_replace_matrix.py index 5436f1e98d..8a215692f5 100644 --- a/tests/variantstudy/model/command/test_replace_matrix.py +++ b/tests/variantstudy/model/command/test_replace_matrix.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock, patch import numpy as np @@ -20,7 +32,7 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): area1 = "Area1" area1_id = transform_name_to_id(area1) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area1, "command_context": command_context, @@ -28,7 +40,7 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): ).apply(empty_study) target_element = f"input/hydro/common/capacity/maxpower_{area1_id}" - replace_matrix = ReplaceMatrix.parse_obj( + replace_matrix = ReplaceMatrix.model_validate( { "target": target_element, "matrix": [[0]], @@ -44,7 +56,7 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): assert matrix_id in target_path.read_text() target_element = "fake/matrix/path" - replace_matrix = ReplaceMatrix.parse_obj( + replace_matrix = ReplaceMatrix.model_validate( { "target": target_element, "matrix": [[0]], diff --git a/tests/variantstudy/model/command/test_update_comments.py b/tests/variantstudy/model/command/test_update_comments.py index a93de8538c..ec91a59bf6 100644 --- a/tests/variantstudy/model/command/test_update_comments.py +++ b/tests/variantstudy/model/command/test_update_comments.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock import pytest diff --git a/tests/variantstudy/model/command/test_update_config.py b/tests/variantstudy/model/command/test_update_config.py index 999adb6c70..bbce0a45c1 100644 --- a/tests/variantstudy/model/command/test_update_config.py +++ b/tests/variantstudy/model/command/test_update_config.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import json from unittest.mock import Mock, patch @@ -20,7 +32,7 @@ def test_update_config(empty_study: FileStudy, command_context: CommandContext): area1 = "Area1" area1_id = transform_name_to_id(area1) - CreateArea.parse_obj( + CreateArea.model_validate( { "area_name": area1, "command_context": command_context, diff --git a/tests/variantstudy/model/command/test_update_rawfile.py b/tests/variantstudy/model/command/test_update_rawfile.py index 00cfd52b99..61247d861e 100644 --- a/tests/variantstudy/model/command/test_update_rawfile.py +++ b/tests/variantstudy/model/command/test_update_rawfile.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import base64 import os.path from pathlib import Path diff --git a/tests/variantstudy/model/test_variant_model.py b/tests/variantstudy/model/test_variant_model.py index 98c73b949f..b51dc8509d 100644 --- a/tests/variantstudy/model/test_variant_model.py +++ b/tests/variantstudy/model/test_variant_model.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import datetime import uuid from pathlib import Path @@ -141,7 +153,7 @@ def test_commands_service( repository=variant_study_service.repository, ) results = generator.generate_snapshot(saved_id, jwt_user, denormalize=False) - assert results.dict() == { + assert results.model_dump() == { "success": True, "details": [ { diff --git a/tests/variantstudy/test_command_factory.py b/tests/variantstudy/test_command_factory.py index b781895743..b78ba393e5 100644 --- a/tests/variantstudy/test_command_factory.py +++ b/tests/variantstudy/test_command_factory.py @@ -1,6 +1,19 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import importlib import itertools import pkgutil +from typing import List, Set from unittest.mock import Mock import pytest @@ -13,18 +26,385 @@ from antarest.study.storage.variantstudy.model.command.icommand import ICommand from antarest.study.storage.variantstudy.model.model import CommandDTO +COMMANDS: List[CommandDTO] = [ + CommandDTO( + action=CommandName.CREATE_AREA.value, + args={"area_name": "area_name"}, + ), + CommandDTO( + action=CommandName.CREATE_AREA.value, + args=[ + {"area_name": "area_name"}, + {"area_name": "area2"}, + ], + ), + CommandDTO( + action=CommandName.REMOVE_AREA.value, + args={"id": "id"}, + ), + CommandDTO( + action=CommandName.REMOVE_AREA.value, + args=[{"id": "id"}], + ), + CommandDTO( + action=CommandName.CREATE_DISTRICT.value, + args={ + "name": "id", + "filter_items": ["a"], + "output": True, + "comments": "", + }, + ), + CommandDTO( + action=CommandName.CREATE_DISTRICT.value, + args=[ + { + "name": "id", + "base_filter": "add-all", + "output": True, + "comments": "", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_DISTRICT.value, + args={"id": "id"}, + ), + CommandDTO( + action=CommandName.REMOVE_DISTRICT.value, + args=[{"id": "id"}], + ), + CommandDTO( + action=CommandName.CREATE_LINK.value, + args={ + "area1": "area1", + "area2": "area2", + "parameters": {}, + "series": "series", + }, + ), + CommandDTO( + action=CommandName.CREATE_LINK.value, + args=[ + { + "area1": "area1", + "area2": "area2", + "parameters": {}, + "series": "series", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_LINK.value, + args={ + "area1": "area1", + "area2": "area2", + }, + ), + CommandDTO( + action=CommandName.REMOVE_LINK.value, + args=[ + { + "area1": "area1", + "area2": "area2", + } + ], + ), + CommandDTO( + action=CommandName.CREATE_BINDING_CONSTRAINT.value, + args={"name": "name"}, + ), + CommandDTO( + action=CommandName.CREATE_BINDING_CONSTRAINT.value, + args=[ + { + "name": "name", + "enabled": True, + "time_step": "hourly", + "operator": "equal", + "values": "values", + "group": "group_1", + }, + ], + ), + CommandDTO( + action=CommandName.UPDATE_BINDING_CONSTRAINT.value, + args={ + "id": "id", + "enabled": True, + "time_step": "hourly", + "operator": "equal", + "values": "values", + }, + ), + CommandDTO( + action=CommandName.UPDATE_BINDING_CONSTRAINT.value, + args=[ + { + "id": "id", + "enabled": True, + "time_step": "hourly", + "operator": "equal", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_BINDING_CONSTRAINT.value, + args={"id": "id"}, + ), + CommandDTO( + action=CommandName.REMOVE_BINDING_CONSTRAINT.value, + args=[{"id": "id"}], + ), + CommandDTO( + action=CommandName.CREATE_THERMAL_CLUSTER.value, + args={ + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "group": "group", + "unitcount": "unitcount", + "nominalcapacity": "nominalcapacity", + "marginal-cost": "marginal-cost", + "market-bid-cost": "market-bid-cost", + }, + "prepro": "prepro", + "modulation": "modulation", + }, + ), + CommandDTO( + action=CommandName.CREATE_THERMAL_CLUSTER.value, + args=[ + { + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "group": "group", + "unitcount": "unitcount", + "nominalcapacity": "nominalcapacity", + "marginal-cost": "marginal-cost", + "market-bid-cost": "market-bid-cost", + }, + "prepro": "prepro", + "modulation": "modulation", + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_THERMAL_CLUSTER.value, + args={"area_id": "area_name", "cluster_id": "cluster_name"}, + ), + CommandDTO( + action=CommandName.REMOVE_THERMAL_CLUSTER.value, + args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], + ), + CommandDTO( + action=CommandName.CREATE_RENEWABLES_CLUSTER.value, + args={ + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "name": "name", + "ts-interpretation": "power-generation", + }, + }, + ), + CommandDTO( + action=CommandName.CREATE_RENEWABLES_CLUSTER.value, + args=[ + { + "area_id": "area_name", + "cluster_name": "cluster_name", + "parameters": { + "name": "name", + "ts-interpretation": "power-generation", + }, + } + ], + ), + CommandDTO( + action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, + args={"area_id": "area_name", "cluster_id": "cluster_name"}, + ), + CommandDTO( + action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, + args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], + ), + CommandDTO( + action=CommandName.REPLACE_MATRIX.value, + args={"target": "target_element", "matrix": "matrix"}, + ), + CommandDTO( + action=CommandName.REPLACE_MATRIX.value, + args=[{"target": "target_element", "matrix": "matrix"}], + ), + CommandDTO( + action=CommandName.UPDATE_CONFIG.value, + args={"target": "target", "data": {}}, + ), + CommandDTO( + action=CommandName.UPDATE_CONFIG.value, + args=[{"target": "target", "data": {}}], + ), + CommandDTO( + action=CommandName.UPDATE_COMMENTS.value, + args={"comments": "comments"}, + ), + CommandDTO( + action=CommandName.UPDATE_COMMENTS.value, + args=[{"comments": "comments"}], + ), + CommandDTO( + action=CommandName.UPDATE_FILE.value, + args={ + "target": "settings/resources/study", + "b64Data": "", + }, + ), + CommandDTO( + action=CommandName.UPDATE_DISTRICT.value, + args={"id": "id", "filter_items": ["a"]}, + ), + CommandDTO( + action=CommandName.UPDATE_DISTRICT.value, + args=[{"id": "id", "base_filter": "add-all"}], + ), + CommandDTO( + action=CommandName.UPDATE_PLAYLIST.value, + args=[{"active": True, "items": [1, 3], "reverse": False}], + ), + CommandDTO( + action=CommandName.UPDATE_PLAYLIST.value, + args={ + "active": True, + "items": [1, 3], + "weights": {1: 5.0}, + "reverse": False, + }, + ), + CommandDTO( + action=CommandName.UPDATE_SCENARIO_BUILDER.value, + args={ + "data": { + "ruleset test": { + "l": {"area1": {"0": 1}}, + "ntc": {"area1 / area2": {"1": 23}}, + "t": {"area1": {"thermal": {"1": 2}}}, + }, + } + }, + ), + CommandDTO( + action=CommandName.CREATE_ST_STORAGE.value, + args={ + "area_id": "area 1", + "parameters": { + "name": "Storage 1", + "group": "Battery", + "injectionnominalcapacity": 0, + "withdrawalnominalcapacity": 0, + "reservoircapacity": 0, + "efficiency": 1, + "initiallevel": 0, + "initialleveloptim": False, + }, + "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", + "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", + "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", + "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", + "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", + }, + ), + CommandDTO( + action=CommandName.CREATE_ST_STORAGE.value, + args=[ + { + "area_id": "area 1", + "parameters": { + "efficiency": 1, + "group": "Battery", + "initiallevel": 0, + "initialleveloptim": False, + "injectionnominalcapacity": 0, + "name": "Storage 1", + "reservoircapacity": 0, + "withdrawalnominalcapacity": 0, + }, + "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", + "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", + "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", + "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", + "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", + }, + { + "area_id": "area 1", + "parameters": { + "efficiency": 0.94, + "group": "Battery", + "initiallevel": 0, + "initialleveloptim": False, + "injectionnominalcapacity": 0, + "name": "Storage 2", + "reservoircapacity": 0, + "withdrawalnominalcapacity": 0, + }, + "pmax_injection": "matrix://3f5b3746-3995-49b7-a6da-622633472e05", + "pmax_withdrawal": "matrix://4b64a31f-927b-4887-b4cd-adcddd39bdcd", + "lower_rule_curve": "matrix://16c7c3ae-9824-4ef2-aa68-51145884b025", + "upper_rule_curve": "matrix://9a6104e9-990a-415f-a6e2-57507e13b58c", + "inflows": "matrix://e8923768-9bdd-40c2-a6ea-2da2523be727", + }, + ], + ), + CommandDTO( + action=CommandName.REMOVE_ST_STORAGE.value, + args={ + "area_id": "area 1", + "storage_id": "storage 1", + }, + ), + CommandDTO( + action=CommandName.REMOVE_ST_STORAGE.value, + args=[ + { + "area_id": "area 1", + "storage_id": "storage 1", + }, + { + "area_id": "area 1", + "storage_id": "storage 2", + }, + ], + ), + CommandDTO( + action=CommandName.GENERATE_THERMAL_CLUSTER_TIMESERIES.value, + args=[{}], + ), +] + + +@pytest.fixture +def command_factory() -> CommandFactory: + def get_matrix_id(matrix: str) -> str: + # str.removeprefix() is not available in Python 3.8 + prefix = "matrix://" + if matrix.startswith(prefix): + return matrix[len(prefix) :] + return matrix + + return CommandFactory( + generator_matrix_constants=Mock(spec=GeneratorMatrixConstants), + matrix_service=Mock(spec=MatrixService, get_matrix_id=get_matrix_id), + patch_service=Mock(spec=PatchService), + ) + class TestCommandFactory: - # noinspection SpellCheckingInspection - def setup_class(self): + def _get_command_classes(self) -> Set[str]: """ - Set up the test class. - Imports all modules from the `antarest.study.storage.variantstudy.model.command` package and creates a set of command class names derived from the `ICommand` abstract class. The objective is to ensure that the unit test covers all commands in this package. - - This method is executed once before any tests in the test class are run. """ for module_loader, name, ispkg in pkgutil.iter_modules(["antarest/study/storage/variantstudy/model/command"]): importlib.import_module( @@ -32,383 +412,21 @@ def setup_class(self): package="antarest.study.storage.variantstudy.model.command", ) abstract_commands = {"AbstractBindingConstraintCommand"} - self.command_class_set = { - cmd.__name__ for cmd in ICommand.__subclasses__() if cmd.__name__ not in abstract_commands - } + return {cmd.__name__ for cmd in ICommand.__subclasses__() if cmd.__name__ not in abstract_commands} + + def test_all_commands_are_tested(self, command_factory: CommandFactory): + commands = sum([command_factory.to_command(command_dto=cmd) for cmd in COMMANDS], []) + tested_classes = {c.__class__.__name__ for c in commands} + + assert self._get_command_classes().issubset(tested_classes) # noinspection SpellCheckingInspection @pytest.mark.parametrize( "command_dto", - [ - CommandDTO( - action=CommandName.CREATE_AREA.value, - args={"area_name": "area_name"}, - ), - CommandDTO( - action=CommandName.CREATE_AREA.value, - args=[ - {"area_name": "area_name"}, - {"area_name": "area2"}, - ], - ), - CommandDTO( - action=CommandName.REMOVE_AREA.value, - args={"id": "id"}, - ), - CommandDTO( - action=CommandName.REMOVE_AREA.value, - args=[{"id": "id"}], - ), - CommandDTO( - action=CommandName.CREATE_DISTRICT.value, - args={ - "name": "id", - "filter_items": ["a"], - "output": True, - "comments": "", - }, - ), - CommandDTO( - action=CommandName.CREATE_DISTRICT.value, - args=[ - { - "name": "id", - "base_filter": "add-all", - "output": True, - "comments": "", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_DISTRICT.value, - args={"id": "id"}, - ), - CommandDTO( - action=CommandName.REMOVE_DISTRICT.value, - args=[{"id": "id"}], - ), - CommandDTO( - action=CommandName.CREATE_LINK.value, - args={ - "area1": "area1", - "area2": "area2", - "parameters": {}, - "series": "series", - }, - ), - CommandDTO( - action=CommandName.CREATE_LINK.value, - args=[ - { - "area1": "area1", - "area2": "area2", - "parameters": {}, - "series": "series", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_LINK.value, - args={ - "area1": "area1", - "area2": "area2", - }, - ), - CommandDTO( - action=CommandName.REMOVE_LINK.value, - args=[ - { - "area1": "area1", - "area2": "area2", - } - ], - ), - CommandDTO( - action=CommandName.CREATE_BINDING_CONSTRAINT.value, - args={"name": "name"}, - ), - CommandDTO( - action=CommandName.CREATE_BINDING_CONSTRAINT.value, - args=[ - { - "name": "name", - "enabled": True, - "time_step": "hourly", - "operator": "equal", - "values": "values", - "group": "group_1", - }, - ], - ), - CommandDTO( - action=CommandName.UPDATE_BINDING_CONSTRAINT.value, - args={ - "id": "id", - "enabled": True, - "time_step": "hourly", - "operator": "equal", - "values": "values", - }, - ), - CommandDTO( - action=CommandName.UPDATE_BINDING_CONSTRAINT.value, - args=[ - { - "id": "id", - "enabled": True, - "time_step": "hourly", - "operator": "equal", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_BINDING_CONSTRAINT.value, - args={"id": "id"}, - ), - CommandDTO( - action=CommandName.REMOVE_BINDING_CONSTRAINT.value, - args=[{"id": "id"}], - ), - CommandDTO( - action=CommandName.CREATE_THERMAL_CLUSTER.value, - args={ - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "group": "group", - "unitcount": "unitcount", - "nominalcapacity": "nominalcapacity", - "marginal-cost": "marginal-cost", - "market-bid-cost": "market-bid-cost", - }, - "prepro": "prepro", - "modulation": "modulation", - }, - ), - CommandDTO( - action=CommandName.CREATE_THERMAL_CLUSTER.value, - args=[ - { - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "group": "group", - "unitcount": "unitcount", - "nominalcapacity": "nominalcapacity", - "marginal-cost": "marginal-cost", - "market-bid-cost": "market-bid-cost", - }, - "prepro": "prepro", - "modulation": "modulation", - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_THERMAL_CLUSTER.value, - args={"area_id": "area_name", "cluster_id": "cluster_name"}, - ), - CommandDTO( - action=CommandName.REMOVE_THERMAL_CLUSTER.value, - args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], - ), - CommandDTO( - action=CommandName.CREATE_RENEWABLES_CLUSTER.value, - args={ - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "name": "name", - "ts-interpretation": "power-generation", - }, - }, - ), - CommandDTO( - action=CommandName.CREATE_RENEWABLES_CLUSTER.value, - args=[ - { - "area_id": "area_name", - "cluster_name": "cluster_name", - "parameters": { - "name": "name", - "ts-interpretation": "power-generation", - }, - } - ], - ), - CommandDTO( - action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, - args={"area_id": "area_name", "cluster_id": "cluster_name"}, - ), - CommandDTO( - action=CommandName.REMOVE_RENEWABLES_CLUSTER.value, - args=[{"area_id": "area_name", "cluster_id": "cluster_name"}], - ), - CommandDTO( - action=CommandName.REPLACE_MATRIX.value, - args={"target": "target_element", "matrix": "matrix"}, - ), - CommandDTO( - action=CommandName.REPLACE_MATRIX.value, - args=[{"target": "target_element", "matrix": "matrix"}], - ), - CommandDTO( - action=CommandName.UPDATE_CONFIG.value, - args={"target": "target", "data": {}}, - ), - CommandDTO( - action=CommandName.UPDATE_CONFIG.value, - args=[{"target": "target", "data": {}}], - ), - CommandDTO( - action=CommandName.UPDATE_COMMENTS.value, - args={"comments": "comments"}, - ), - CommandDTO( - action=CommandName.UPDATE_COMMENTS.value, - args=[{"comments": "comments"}], - ), - CommandDTO( - action=CommandName.UPDATE_FILE.value, - args={ - "target": "settings/resources/study", - "b64Data": "", - }, - ), - CommandDTO( - action=CommandName.UPDATE_DISTRICT.value, - args={"id": "id", "filter_items": ["a"]}, - ), - CommandDTO( - action=CommandName.UPDATE_DISTRICT.value, - args=[{"id": "id", "base_filter": "add-all"}], - ), - CommandDTO( - action=CommandName.UPDATE_PLAYLIST.value, - args=[{"active": True, "items": [1, 3], "reverse": False}], - ), - CommandDTO( - action=CommandName.UPDATE_PLAYLIST.value, - args={ - "active": True, - "items": [1, 3], - "weights": {1: 5.0}, - "reverse": False, - }, - ), - CommandDTO( - action=CommandName.UPDATE_SCENARIO_BUILDER.value, - args={ - "data": { - "ruleset test": { - "l": {"area1": {"0": 1}}, - "ntc": {"area1 / area2": {"1": 23}}, - "t": {"area1": {"thermal": {"1": 2}}}, - }, - } - }, - ), - CommandDTO( - action=CommandName.CREATE_ST_STORAGE.value, - args={ - "area_id": "area 1", - "parameters": { - "name": "Storage 1", - "group": "Battery", - "injectionnominalcapacity": 0, - "withdrawalnominalcapacity": 0, - "reservoircapacity": 0, - "efficiency": 1, - "initiallevel": 0, - "initialleveloptim": False, - }, - "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", - "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", - "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", - "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", - "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", - }, - ), - CommandDTO( - action=CommandName.CREATE_ST_STORAGE.value, - args=[ - { - "area_id": "area 1", - "parameters": { - "efficiency": 1, - "group": "Battery", - "initiallevel": 0, - "initialleveloptim": False, - "injectionnominalcapacity": 0, - "name": "Storage 1", - "reservoircapacity": 0, - "withdrawalnominalcapacity": 0, - }, - "pmax_injection": "matrix://59ea6c83-6348-466d-9530-c35c51ca4c37", - "pmax_withdrawal": "matrix://5f988548-dadc-4bbb-8ce8-87a544dbf756", - "lower_rule_curve": "matrix://8ce4fcea-cc97-4d2c-b641-a27a53454612", - "upper_rule_curve": "matrix://8ce614c8-c687-41af-8b24-df8a49cc52af", - "inflows": "matrix://df9b25e1-e3f7-4a57-8182-0ff9791439e5", - }, - { - "area_id": "area 1", - "parameters": { - "efficiency": 0.94, - "group": "Battery", - "initiallevel": 0, - "initialleveloptim": False, - "injectionnominalcapacity": 0, - "name": "Storage 2", - "reservoircapacity": 0, - "withdrawalnominalcapacity": 0, - }, - "pmax_injection": "matrix://3f5b3746-3995-49b7-a6da-622633472e05", - "pmax_withdrawal": "matrix://4b64a31f-927b-4887-b4cd-adcddd39bdcd", - "lower_rule_curve": "matrix://16c7c3ae-9824-4ef2-aa68-51145884b025", - "upper_rule_curve": "matrix://9a6104e9-990a-415f-a6e2-57507e13b58c", - "inflows": "matrix://e8923768-9bdd-40c2-a6ea-2da2523be727", - }, - ], - ), - CommandDTO( - action=CommandName.REMOVE_ST_STORAGE.value, - args={ - "area_id": "area 1", - "storage_id": "storage 1", - }, - ), - CommandDTO( - action=CommandName.REMOVE_ST_STORAGE.value, - args=[ - { - "area_id": "area 1", - "storage_id": "storage 1", - }, - { - "area_id": "area 1", - "storage_id": "storage 2", - }, - ], - ), - CommandDTO( - action=CommandName.GENERATE_THERMAL_CLUSTER_TIMESERIES.value, - args=[{}], - ), - ], + COMMANDS, ) @pytest.mark.unit_test - def test_command_factory(self, command_dto: CommandDTO): - def get_matrix_id(matrix: str) -> str: - # str.removeprefix() is not available in Python 3.8 - prefix = "matrix://" - if matrix.startswith(prefix): - return matrix[len(prefix) :] - return matrix - - command_factory = CommandFactory( - generator_matrix_constants=Mock(spec=GeneratorMatrixConstants), - matrix_service=Mock(spec=MatrixService, get_matrix_id=get_matrix_id), - patch_service=Mock(spec=PatchService), - ) + def test_command_factory(self, command_dto: CommandDTO, command_factory: CommandFactory): commands = command_factory.to_command(command_dto=command_dto) if isinstance(command_dto.args, dict): @@ -428,12 +446,6 @@ def get_matrix_id(matrix: str) -> str: assert actual_args == expected_args assert actual_version == expected_version - self.command_class_set.discard(type(commands[0]).__name__) - - def teardown_class(self): - # Check that all command classes have been tested - assert not self.command_class_set - @pytest.mark.unit_test def test_unknown_command(): diff --git a/tests/variantstudy/test_utils.py b/tests/variantstudy/test_utils.py index 2a856be549..d97c3d65a5 100644 --- a/tests/variantstudy/test_utils.py +++ b/tests/variantstudy/test_utils.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from antarest.study.storage.variantstudy.business.utils import transform_command_to_dto from antarest.study.storage.variantstudy.model.command.create_area import CreateArea from antarest.study.storage.variantstudy.model.command.create_link import CreateLink diff --git a/tests/variantstudy/test_variant_command_extractor.py b/tests/variantstudy/test_variant_command_extractor.py index 8545869398..45665cf5cf 100644 --- a/tests/variantstudy/test_variant_command_extractor.py +++ b/tests/variantstudy/test_variant_command_extractor.py @@ -1,3 +1,16 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + + def test_extract(): # Already covered by integration test "test_integration_variantmanager_tool" pass diff --git a/tests/worker/__init__.py b/tests/worker/__init__.py index e69de29bb2..058c6b221a 100644 --- a/tests/worker/__init__.py +++ b/tests/worker/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. diff --git a/tests/worker/test_archive_worker.py b/tests/worker/test_archive_worker.py index a0b6cb505b..12c42ec699 100644 --- a/tests/worker/test_archive_worker.py +++ b/tests/worker/test_archive_worker.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from pathlib import Path from unittest.mock import Mock from zipfile import ZIP_DEFLATED, ZipFile diff --git a/tests/worker/test_archive_worker_service.py b/tests/worker/test_archive_worker_service.py index b8fd4d2e33..65b3971baf 100644 --- a/tests/worker/test_archive_worker_service.py +++ b/tests/worker/test_archive_worker_service.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + from unittest.mock import Mock, patch import pytest diff --git a/tests/worker/test_simulator_worker.py b/tests/worker/test_simulator_worker.py index 58db7ec4eb..791aa3ec3d 100644 --- a/tests/worker/test_simulator_worker.py +++ b/tests/worker/test_simulator_worker.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import os import platform import stat diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index ab67beac57..72b9c4ac00 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import time from pathlib import Path from typing import List diff --git a/tests/xml_compare.py b/tests/xml_compare.py index 19e36b4a68..1f2761737f 100644 --- a/tests/xml_compare.py +++ b/tests/xml_compare.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. + import re import typing as t from xml.etree.ElementTree import Element diff --git a/webapp/.eslintrc.cjs b/webapp/.eslintrc.cjs index 8a4e508acb..29270da704 100644 --- a/webapp/.eslintrc.cjs +++ b/webapp/.eslintrc.cjs @@ -12,10 +12,17 @@ module.exports = { "plugin:react/jsx-runtime", "plugin:react-hooks/recommended", "plugin:jsdoc/recommended-typescript", - "plugin:prettier/recommended", + "plugin:prettier/recommended", // Must be the last one + ], + plugins: [ + "license-header", + "react-refresh", + ], + ignorePatterns: [ + "dist", + "license-header.js", + ".eslintrc.cjs", ], - plugins: ["react-refresh"], - ignorePatterns: ["dist", ".eslintrc.cjs"], parser: "@typescript-eslint/parser", parserOptions: { // `ecmaVersion` is automatically sets by `esXXXX` in `env` @@ -48,6 +55,7 @@ module.exports = { "jsdoc/require-jsdoc": "off", "jsdoc/require-hyphen-before-param-description": "warn", "jsdoc/tag-lines": ["warn", "any", { startLines: 1 }], // Expected 1 line after block description + "license-header/header": ["error", "license-header.js"], "no-console": "warn", "no-param-reassign": [ "error", diff --git a/webapp/.npmrc b/webapp/.npmrc index 4fd021952d..519835e9e2 100644 --- a/webapp/.npmrc +++ b/webapp/.npmrc @@ -1 +1,2 @@ -engine-strict=true \ No newline at end of file +engine-strict=true +save-prefix= # prevent the caret (^) symbol use when installing new dependencies \ No newline at end of file diff --git a/webapp/.prettierignore b/webapp/.prettierignore new file mode 100644 index 0000000000..f8b474f9c3 --- /dev/null +++ b/webapp/.prettierignore @@ -0,0 +1 @@ +license-header.js diff --git a/webapp/license-header.js b/webapp/license-header.js new file mode 100644 index 0000000000..a5bb574db3 --- /dev/null +++ b/webapp/license-header.js @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ \ No newline at end of file diff --git a/webapp/package-lock.json b/webapp/package-lock.json index c326297735..c516722650 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -1,129 +1,122 @@ { "name": "antares-web", - "version": "2.17.5", + "version": "2.17.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "antares-web", - "version": "2.17.5", + "version": "2.17.6", "dependencies": { - "@emotion/react": "11.11.1", - "@emotion/styled": "11.11.0", + "@emotion/react": "11.13.3", + "@emotion/styled": "11.13.0", "@glideapps/glide-data-grid": "6.0.3", - "@handsontable/react": "14.1.0", - "@mui/icons-material": "5.14.11", - "@mui/lab": "5.0.0-alpha.146", - "@mui/material": "5.14.11", - "@mui/x-date-pickers": "6.18.3", + "@handsontable/react": "14.5.0", + "@mui/icons-material": "6.1.1", + "@mui/lab": "6.0.0-beta.10", + "@mui/material": "6.1.1", + "@mui/x-tree-view": "7.18.0", "@reduxjs/toolkit": "1.9.6", - "axios": "1.5.1", - "clsx": "2.0.0", + "axios": "1.7.7", + "clsx": "2.1.1", "d3": "5.16.0", - "debug": "4.3.4", + "debug": "4.3.7", "draft-convert": "2.1.13", "draft-js": "0.11.7", "draftjs-to-html": "0.9.1", - "handsontable": "14.1.0", + "handsontable": "14.5.0", "hoist-non-react-statics": "3.3.2", - "i18next": "23.5.1", - "i18next-browser-languagedetector": "7.1.0", - "i18next-http-backend": "2.4.2", - "immer": "10.0.3", + "i18next": "23.15.1", + "i18next-browser-languagedetector": "8.0.0", + "i18next-http-backend": "2.6.1", + "immer": "10.1.1", "js-cookie": "3.0.5", - "jsoneditor": "9.10.4", - "jwt-decode": "3.1.2", + "jsoneditor": "10.1.0", + "jwt-decode": "4.0.0", "lodash": "4.17.21", - "material-react-table": "2.0.5", - "moment": "2.29.4", + "material-react-table": "3.0.1", + "moment": "2.30.1", "notistack": "3.0.1", - "plotly.js": "2.26.1", - "ramda": "0.29.0", - "ramda-adjunct": "4.1.1", - "react": "18.2.0", + "plotly.js": "2.35.2", + "ramda": "0.30.1", + "ramda-adjunct": "5.1.0", + "react": "18.3.1", "react-beautiful-dnd": "13.1.1", "react-color": "2.19.3", "react-d3-graph": "2.6.0", - "react-dom": "18.2.0", + "react-dom": "18.3.1", "react-dropzone": "14.2.3", - "react-hook-form": "7.47.0", - "react-i18next": "13.2.2", + "react-hook-form": "7.53.0", + "react-i18next": "15.0.2", "react-json-view": "1.21.3", "react-plotly.js": "2.6.0", "react-redux": "8.1.3", "react-router": "6.3.0", "react-router-dom": "6.3.0", "react-split": "2.0.14", - "react-use": "17.4.0", - "react-virtualized-auto-sizer": "1.0.20", - "react-window": "1.8.9", + "react-syntax-highlighter": "15.5.0", + "react-use": "17.5.1", + "react-virtualized-auto-sizer": "1.0.24", + "react-window": "1.8.10", "redux": "4.2.1", "redux-thunk": "2.4.2", - "swagger-ui-react": "5.9.0", + "swagger-ui-react": "5.17.14", "ts-toolbelt": "9.6.0", "use-undo": "1.1.1", - "uuid": "9.0.1", + "uuid": "10.0.0", "xml-js": "1.6.11" }, "devDependencies": { - "@testing-library/jest-dom": "6.4.6", - "@testing-library/react": "16.0.0", + "@testing-library/jest-dom": "6.5.0", + "@testing-library/react": "16.0.1", "@testing-library/user-event": "14.5.2", - "@total-typescript/ts-reset": "0.5.1", + "@total-typescript/ts-reset": "0.6.1", "@types/d3": "5.16.0", - "@types/debug": "4.1.9", - "@types/draft-convert": "2.1.5", - "@types/draft-js": "0.11.13", - "@types/draftjs-to-html": "0.8.2", - "@types/js-cookie": "3.0.4", + "@types/debug": "4.1.12", + "@types/draft-convert": "2.1.8", + "@types/draft-js": "0.11.18", + "@types/draftjs-to-html": "0.8.4", + "@types/js-cookie": "3.0.6", "@types/jsoneditor": "9.9.5", - "@types/lodash": "4.14.199", - "@types/node": "18.16.1", - "@types/ramda": "0.29.5", - "@types/react": "18.2.24", - "@types/react-beautiful-dnd": "13.1.5", - "@types/react-color": "3.0.7", + "@types/lodash": "4.17.9", + "@types/node": "22.7.3", + "@types/ramda": "0.30.2", + "@types/react": "18.3.9", + "@types/react-beautiful-dnd": "13.1.8", + "@types/react-color": "3.0.12", "@types/react-d3-graph": "2.6.5", - "@types/react-dom": "18.2.8", - "@types/react-plotly.js": "2.6.1", - "@types/react-virtualized-auto-sizer": "1.0.1", - "@types/react-window": "1.8.6", - "@types/redux-logger": "3.0.10", - "@types/swagger-ui-react": "4.18.1", + "@types/react-dom": "18.3.0", + "@types/react-plotly.js": "2.6.3", + "@types/react-syntax-highlighter": "15.5.13", + "@types/react-virtualized-auto-sizer": "1.0.4", + "@types/react-window": "1.8.8", + "@types/swagger-ui-react": "4.18.3", "@types/testing-library__jest-dom": "6.0.0", - "@types/uuid": "9.0.4", - "@typescript-eslint/eslint-plugin": "6.14.0", - "@typescript-eslint/parser": "6.14.0", - "@vitejs/plugin-react-swc": "3.5.0", - "@vitest/coverage-v8": "1.6.0", - "@vitest/ui": "1.6.0", - "eslint": "8.55.0", - "eslint-config-prettier": "9.0.0", - "eslint-plugin-jsdoc": "48.2.0", - "eslint-plugin-prettier": "5.0.0", - "eslint-plugin-react": "7.33.2", - "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-react-refresh": "0.4.5", - "husky": "8.0.3", - "jsdom": "24.1.0", - "prettier": "3.0.3", - "typescript": "5.2.2", - "vite": "5.0.8", - "vitest": "1.6.0" + "@types/uuid": "10.0.0", + "@typescript-eslint/eslint-plugin": "7.2.0", + "@typescript-eslint/parser": "7.2.0", + "@vitejs/plugin-react-swc": "3.7.0", + "@vitest/coverage-v8": "2.1.1", + "@vitest/ui": "2.1.1", + "eslint": "8.57.1", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-jsdoc": "48.10.0", + "eslint-plugin-license-header": "0.6.1", + "eslint-plugin-prettier": "5.2.1", + "eslint-plugin-react": "7.37.0", + "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-refresh": "0.4.12", + "husky": "9.1.6", + "jsdom": "25.0.1", + "prettier": "3.3.3", + "typescript": "5.4.5", + "vite": "5.4.8", + "vitest": "2.1.1" }, "engines": { "node": "18.16.1" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@adobe/css-tools": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", @@ -155,28 +148,28 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", - "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -196,20 +189,12 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dependencies": { - "@babel/types": "^7.24.7", + "@babel/types": "^7.25.6", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -219,13 +204,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", - "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -233,61 +218,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", @@ -301,15 +231,14 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", - "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -319,9 +248,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", - "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "engines": { "node": ">=6.9.0" } @@ -338,21 +267,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", - "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "engines": { "node": ">=6.9.0" } @@ -366,20 +284,20 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", - "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", - "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" }, "engines": { "node": ">=6.9.0" @@ -399,74 +317,13 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.25.6" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", - "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -513,12 +370,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", - "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-simple-access": "^7.24.7" }, "engines": { @@ -529,9 +386,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", - "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -540,9 +397,9 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.8.tgz", - "integrity": "sha512-2ZzmcDugdm0/YQKFVYsXiwUN7USPX8PM7cytpb4PFl87fM+qYPSvTZX//8tyeJB1j0YDmafBJEbl5f8NfLyuKw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.6.tgz", + "integrity": "sha512-Gz0Nrobx8szge6kQQ5Z5MX9L3ObqNwCQY1PSwSNzreFL7aHGxv8Fp2j3ETV6/wWdbiV+mW6OSm8oQhg3Tcsniw==", "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.14.0" @@ -552,31 +409,28 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", - "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -584,20 +438,12 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", - "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "dependencies": { - "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, @@ -612,9 +458,9 @@ "dev": true }, "node_modules/@braintree/sanitize-url": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", - "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==" + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.0.2.tgz", + "integrity": "sha512-NVf/1YycDMs6+FxS0Tb/W8MjJRDQdXF+tBfDtZ5UZeiRUkTmwKc4vmYCKZTyymfJk1gnMsauvZSX/HiV9jOABw==" }, "node_modules/@choojs/findup": { "version": "0.2.1", @@ -628,15 +474,15 @@ } }, "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", @@ -646,47 +492,47 @@ } }, "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", "dependencies": { - "@emotion/memoize": "^0.8.1" + "@emotion/memoize": "^0.9.0" } }, "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" }, "node_modules/@emotion/react": { - "version": "11.11.1", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz", - "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==", + "version": "11.13.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz", + "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==", "dependencies": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.2", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { @@ -699,33 +545,33 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", - "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz", + "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==", "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.1", "csstype": "^3.0.2" } }, "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" }, "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", "dependencies": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1" + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", @@ -738,36 +584,36 @@ } }, "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz", + "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==" }, "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", - "integrity": "sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", + "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", "dev": true, "dependencies": { "comment-parser": "1.4.1", - "esquery": "^1.5.0", + "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.0.0" }, "engines": { @@ -775,9 +621,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", "cpu": [ "ppc64" ], @@ -791,9 +637,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", "cpu": [ "arm" ], @@ -807,9 +653,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", "cpu": [ "arm64" ], @@ -823,9 +669,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", "cpu": [ "x64" ], @@ -839,9 +685,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", "cpu": [ "arm64" ], @@ -855,9 +701,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", "cpu": [ "x64" ], @@ -871,9 +717,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", "cpu": [ "arm64" ], @@ -887,9 +733,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", "cpu": [ "x64" ], @@ -903,9 +749,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", "cpu": [ "arm" ], @@ -919,9 +765,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", "cpu": [ "arm64" ], @@ -935,9 +781,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", "cpu": [ "ia32" ], @@ -951,9 +797,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", "cpu": [ "loong64" ], @@ -967,9 +813,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", "cpu": [ "mips64el" ], @@ -983,9 +829,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", "cpu": [ "ppc64" ], @@ -999,9 +845,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", "cpu": [ "riscv64" ], @@ -1015,9 +861,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", "cpu": [ "s390x" ], @@ -1031,9 +877,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ "x64" ], @@ -1047,9 +893,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", "cpu": [ "x64" ], @@ -1063,9 +909,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", "cpu": [ "x64" ], @@ -1079,9 +925,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", "cpu": [ "x64" ], @@ -1095,9 +941,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", "cpu": [ "arm64" ], @@ -1111,9 +957,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", "cpu": [ "ia32" ], @@ -1127,9 +973,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", "cpu": [ "x64" ], @@ -1158,9 +1004,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1189,46 +1035,75 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/js": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", - "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", - "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=14" + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@floating-ui/core": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", - "integrity": "sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", "dependencies": { - "@floating-ui/utils": "^0.2.0" + "@floating-ui/utils": "^0.2.8" } }, "node_modules/@floating-ui/dom": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.4.tgz", - "integrity": "sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==", + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", + "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", "dependencies": { - "@floating-ui/core": "^1.5.3", - "@floating-ui/utils": "^0.2.0" + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.6.tgz", - "integrity": "sha512-IB8aCRFxr8nFkdYZgH+Otd9EVQPJoynxeFRGTB8voPoZMRWo8XjYuCRgpI1btvuKY69XMiLnW+ym7zoBHM90Rw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", "dependencies": { - "@floating-ui/dom": "^1.5.4" + "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "react": ">=16.8.0", @@ -1236,9 +1111,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", - "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" }, "node_modules/@glideapps/glide-data-grid": { "version": "6.0.3", @@ -1263,20 +1138,21 @@ "integrity": "sha512-1VN6N38t5/DcjJ7y7XUYrDx1LuzvvzlrFdBdMG90Qo1xc8+LXHqbWbsTEm5Ec5gXTEbDEO53vUT35R+2COmOyg==" }, "node_modules/@handsontable/react": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@handsontable/react/-/react-14.1.0.tgz", - "integrity": "sha512-tgqeiiVIG1PBczaq5/pwtQBlhmldej4wEfqx3L7aJn1fcbArGGsCbRdNd6aneH4BP79aC/ajiwr2vVx7NeAcgg==", + "version": "14.5.0", + "resolved": "https://registry.npmjs.org/@handsontable/react/-/react-14.5.0.tgz", + "integrity": "sha512-Z6weZTELY1hqgW8TDno000xScd+I1sQ0DcswX2AdnCCwvvQkmC74xmIREalwtFE9CCi0Y/kiSvq/G0bYgl//pQ==", "peerDependencies": { "handsontable": ">=14.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -1284,6 +1160,28 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1298,9 +1196,10 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true }, "node_modules/@icons/material": { @@ -1311,25 +1210,57 @@ "react": "*" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { @@ -1361,10 +1292,20 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -1420,28 +1361,6 @@ "react": ">=16" } }, - "node_modules/@linaria/react/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@linaria/react/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@linaria/tags": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/@linaria/tags/-/tags-4.5.4.tgz", @@ -1477,28 +1396,6 @@ "node": "^12.16.0 || >=13.7.0" } }, - "node_modules/@linaria/utils/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@linaria/utils/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@mapbox/geojson-rewind": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz", @@ -1563,25 +1460,55 @@ "node": ">=6.0.0" } }, + "node_modules/@maplibre/maplibre-gl-style-spec": { + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.3.1.tgz", + "integrity": "sha512-5ueL4UDitzVtceQ8J4kY+Px3WK+eZTsmGwha3MBKHKqiHvKrjWWwBCIl1K8BuJSc5OFh83uI8IFNoFvQxX2uUw==", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/unitbezier": "^0.0.1", + "json-stringify-pretty-compact": "^4.0.0", + "minimist": "^1.2.8", + "quickselect": "^2.0.0", + "rw": "^1.3.3", + "sort-object": "^3.0.3", + "tinyqueue": "^3.0.0" + }, + "bin": { + "gl-style-format": "dist/gl-style-format.mjs", + "gl-style-migrate": "dist/gl-style-migrate.mjs", + "gl-style-validate": "dist/gl-style-validate.mjs" + } + }, + "node_modules/@maplibre/maplibre-gl-style-spec/node_modules/@mapbox/unitbezier": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==" + }, + "node_modules/@maplibre/maplibre-gl-style-spec/node_modules/tinyqueue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==" + }, "node_modules/@mui/base": { - "version": "5.0.0-beta.17", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.17.tgz", - "integrity": "sha512-xNbk7iOXrglNdIxFBN0k3ySsPIFLWCnFxqsAYl7CIcDkD9low4kJ7IUuy6ctwx/HAy2fenrT3KXHr1sGjAMgpQ==", - "dependencies": { - "@babel/runtime": "^7.22.15", - "@floating-ui/react-dom": "^2.0.2", - "@mui/types": "^7.2.4", - "@mui/utils": "^5.14.11", + "version": "5.0.0-beta.58", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.58.tgz", + "integrity": "sha512-P0E7ZrxOuyYqBvVv9w8k7wm+Xzx/KRu+BGgFcR2htTsGCpJNQJCSUXNUZ50MUmSU9hzqhwbQWNXhV1MBTl6F7A==", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@floating-ui/react-dom": "^2.1.1", + "@mui/types": "^7.2.15", + "@mui/utils": "6.0.0-rc.0", "@popperjs/core": "^2.11.8", - "clsx": "^2.0.0", + "clsx": "^2.1.1", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -1594,33 +1521,62 @@ } } }, + "node_modules/@mui/base/node_modules/@mui/utils": { + "version": "6.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.0.0-rc.0.tgz", + "integrity": "sha512-tBp0ILEXDL0bbDDT8PnZOjCqSm5Dfk2N0Z45uzRw+wVl6fVvloC9zw8avl+OdX1Bg3ubs/ttKn8nRNv17bpM5A==", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.6.tgz", - "integrity": "sha512-0aoWS4qvk1uzm9JBs83oQmIMIQeTBUeqqu8u+3uo2tMznrB5fIKqQVCbCgq+4Tm4jG+5F7dIvnjvQ2aV7UKtdw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.1.tgz", + "integrity": "sha512-VdQC1tPIIcZAnf62L2M1eQif0x2vlKg3YK4kGYbtijSH4niEgI21GnstykW1vQIs+Bc6L+Hua2GATYVjilJ22A==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.14.11", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.14.11.tgz", - "integrity": "sha512-aHReLasBuS/+hhPzbZCgZ0eTcZ2QRnoC2WNK7XvdAf3l+LjC1flzjh6GWw1tZJ5NHnZ+bivdwtLFQ8XTR96JkA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.1.1.tgz", + "integrity": "sha512-sy/YKwcLPW8VcacNP2uWMYR9xyWuwO9NN9FXuGEU90bRshBXj8pdKk+joe3TCW7oviVS3zXLHlc94wQ0jNsQRQ==", "dependencies": { - "@babel/runtime": "^7.22.15" + "@babel/runtime": "^7.25.6" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@mui/material": "^5.0.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@mui/material": "^6.1.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -1629,33 +1585,33 @@ } }, "node_modules/@mui/lab": { - "version": "5.0.0-alpha.146", - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.146.tgz", - "integrity": "sha512-azkSNz/F4VAzXdXG1Yu/pdWiMQY8dRpwHycLCQCK7oql5AOVh1pVEmw5+nMT161oc5bOzxBkIsNGPCBwXIZ7Ww==", - "dependencies": { - "@babel/runtime": "^7.22.15", - "@mui/base": "5.0.0-beta.17", - "@mui/system": "^5.14.11", - "@mui/types": "^7.2.4", - "@mui/utils": "^5.14.11", - "@mui/x-tree-view": "6.0.0-alpha.1", - "clsx": "^2.0.0", + "version": "6.0.0-beta.10", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.0-beta.10.tgz", + "integrity": "sha512-eqCBz5SZS8Un9To3UcjH01AxkOOgvme/g0ZstFC8Nz1Kg5/EJMA0ByhKS5AvUMzUKrv0FXMdbuPqbBvF3bVrXg==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/base": "5.0.0-beta.58", + "@mui/system": "^6.1.1", + "@mui/types": "^7.2.17", + "@mui/utils": "^6.1.1", + "clsx": "^2.1.1", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material": "^5.0.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "@mui/material": "^6.1.1", + "@mui/material-pigment-css": "^6.1.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -1664,42 +1620,46 @@ "@emotion/styled": { "optional": true }, + "@mui/material-pigment-css": { + "optional": true + }, "@types/react": { "optional": true } } }, "node_modules/@mui/material": { - "version": "5.14.11", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.11.tgz", - "integrity": "sha512-DnSdJzcR7lwG12JA5L2t8JF+RDzMygu5rCNW+logWb/KW2/TRzwLyVWO+CorHTBjBRd38DBxnwOCDiYkDd+N3A==", - "dependencies": { - "@babel/runtime": "^7.22.15", - "@mui/base": "5.0.0-beta.17", - "@mui/core-downloads-tracker": "^5.14.11", - "@mui/system": "^5.14.11", - "@mui/types": "^7.2.4", - "@mui/utils": "^5.14.11", - "@types/react-transition-group": "^4.4.6", - "clsx": "^2.0.0", - "csstype": "^3.1.2", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.1.tgz", + "integrity": "sha512-b+eULldTqtqTCbN++2BtBWCir/1LwEYw+2mIlOt2GiEUh1EBBw4/wIukGKKNt3xrCZqRA80yLLkV6tF61Lq3cA==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/core-downloads-tracker": "^6.1.1", + "@mui/system": "^6.1.1", + "@mui/types": "^7.2.17", + "@mui/utils": "^6.1.1", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.11", + "clsx": "^2.1.1", + "csstype": "^3.1.3", "prop-types": "^15.8.1", - "react-is": "^18.2.0", + "react-is": "^18.3.1", "react-transition-group": "^4.4.5" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "@mui/material-pigment-css": "^6.1.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -1708,30 +1668,33 @@ "@emotion/styled": { "optional": true }, + "@mui/material-pigment-css": { + "optional": true + }, "@types/react": { "optional": true } } }, "node_modules/@mui/private-theming": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.6.tgz", - "integrity": "sha512-ZBX9E6VNUSscUOtU8uU462VvpvBS7eFl5VfxAzTRVQBHflzL+5KtnGrebgf6Nd6cdvxa1o0OomiaxSKoN2XDmg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.1.tgz", + "integrity": "sha512-JlrjIdhyZUtewtdAuUsvi3ZnO0YS49IW4Mfz19ZWTlQ0sDGga6LNPVwHClWr2/zJK2we2BQx9/i8M32rgKuzrg==", "dependencies": { - "@babel/runtime": "^7.23.8", - "@mui/utils": "^5.15.6", + "@babel/runtime": "^7.25.6", + "@mui/utils": "^6.1.1", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -1740,17 +1703,18 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.6.tgz", - "integrity": "sha512-KAn8P8xP/WigFKMlEYUpU9z2o7jJnv0BG28Qu1dhNQVutsLVIFdRf5Nb+0ijp2qgtcmygQ0FtfRuXv5LYetZTg==", - "dependencies": { - "@babel/runtime": "^7.23.8", - "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.1.tgz", + "integrity": "sha512-HJyIoMpFb11fnHuRtUILOXgq6vj4LhIlE8maG4SwP/W+E5sa7HFexhnB3vOMT7bKys4UKNxhobC8jwWxYilGsA==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@emotion/cache": "^11.13.1", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", @@ -1759,7 +1723,7 @@ "peerDependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -1771,21 +1735,21 @@ } }, "node_modules/@mui/system": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.6.tgz", - "integrity": "sha512-J01D//u8IfXvaEHMBQX5aO2l7Q+P15nt96c4NskX7yp5/+UuZP8XCQJhtBtLuj+M2LLyXHYGmCPeblsmmscP2Q==", - "dependencies": { - "@babel/runtime": "^7.23.8", - "@mui/private-theming": "^5.15.6", - "@mui/styled-engine": "^5.15.6", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.6", - "clsx": "^2.1.0", - "csstype": "^3.1.2", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.1.tgz", + "integrity": "sha512-PaYsCz2tUOcpu3T0okDEsSuP/yCDIj9JZ4Tox1JovRSKIjltHpXPsXZSGr3RiWdtM1MTQMFMCZzu0+CKbyy+Kw==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/private-theming": "^6.1.1", + "@mui/styled-engine": "^6.1.1", + "@mui/types": "^7.2.17", + "@mui/utils": "^6.1.1", + "clsx": "^2.1.1", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", @@ -1794,8 +1758,8 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -1809,20 +1773,12 @@ } } }, - "node_modules/@mui/system/node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, "node_modules/@mui/types": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", - "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", + "version": "7.2.17", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.17.tgz", + "integrity": "sha512-oyumoJgB6jDV8JFzRqjBo2daUuHpzDjoO/e3IrRhhHo/FxJlaVhET6mcNrKHUq2E+R+q3ql0qAtvQ4rfWHhAeQ==", "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -1831,25 +1787,27 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.6.tgz", - "integrity": "sha512-qfEhf+zfU9aQdbzo1qrSWlbPQhH1nCgeYgwhOVnj9Bn39shJQitEnXpSQpSNag8+uty5Od6PxmlNKPTnPySRKA==", - "dependencies": { - "@babel/runtime": "^7.23.8", - "@types/prop-types": "^15.7.11", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.1.tgz", + "integrity": "sha512-HlRrgdJSPbYDXPpoVMWZV8AE7WcFtAk13rWNWAEVWKSanzBBkymjz3km+Th/Srowsh4pf1fTSP1B0L116wQBYw==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/types": "^7.2.17", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "react-is": "^18.3.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -1858,15 +1816,16 @@ } }, "node_modules/@mui/x-date-pickers": { - "version": "6.18.3", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.18.3.tgz", - "integrity": "sha512-DmJrAAr6EfhuWA9yubANAdeQayAbUppCezdhxkYKwn38G8+HJPZBol0V5fKji+B4jMxruO78lkQYsGUxVxaR7A==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/base": "^5.0.0-beta.22", - "@mui/utils": "^5.14.16", - "@types/react-transition-group": "^4.4.8", - "clsx": "^2.0.0", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.18.0.tgz", + "integrity": "sha512-12tXIoMj9vpS8fS/bS3kWPCoVrH38vNGCxgplI0vOnUrN9rJuYJz3agLPJe1S0xciTw+9W8ZSe3soaW+owoz1Q==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6", + "@mui/x-internals": "7.18.0", + "@types/react-transition-group": "^4.4.11", + "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, @@ -1875,15 +1834,15 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", - "@mui/material": "^5.8.6", - "@mui/system": "^5.8.0", - "date-fns": "^2.25.0", - "date-fns-jalali": "^2.13.0-0", + "@mui/material": "^5.15.14 || ^6.0.0", + "@mui/system": "^5.15.14 || ^6.0.0", + "date-fns": "^2.25.0 || ^3.2.0 || ^4.0.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0", "dayjs": "^1.10.7", "luxon": "^3.0.2", "moment": "^2.29.4", @@ -1922,18 +1881,18 @@ } } }, - "node_modules/@mui/x-date-pickers/node_modules/@mui/base": { - "version": "5.0.0-beta.33", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.33.tgz", - "integrity": "sha512-WcSpoJUw/UYHXpvgtl4HyMar2Ar97illUpqiS/X1gtSBp6sdDW6kB2BJ9OlVQ+Kk/RL2GDp/WHA9sbjAYV35ow==", + "node_modules/@mui/x-date-pickers/node_modules/@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "peer": true, "dependencies": { - "@babel/runtime": "^7.23.8", - "@floating-ui/react-dom": "^2.0.6", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.6", - "@popperjs/core": "^2.11.8", - "clsx": "^2.1.0", - "prop-types": "^15.8.1" + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" }, "engines": { "node": ">=12.0.0" @@ -1944,8 +1903,7 @@ }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -1953,23 +1911,64 @@ } } }, - "node_modules/@mui/x-date-pickers/node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "node_modules/@mui/x-internals": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.18.0.tgz", + "integrity": "sha512-lzCHOWIR0cAIY1bGrWSprYerahbnH5C31ql/2OWCEjcngL2NAV1M6oKI2Vp4HheqzJ822c60UyWyapvyjSzY/A==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6" + }, "engines": { - "node": ">=6" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" + } + }, + "node_modules/@mui/x-internals/node_modules/@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/@mui/x-tree-view": { - "version": "6.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-6.0.0-alpha.1.tgz", - "integrity": "sha512-JUG3HmBrmGEALbCFg1b+i7h726e1dWYZs4db3syO1j+Q++E3nbvE4Lehp5yGTFm+8esH0Tny50tuJaa4WX6VSA==", - "dependencies": { - "@babel/runtime": "^7.22.6", - "@mui/utils": "^5.14.3", - "@types/react-transition-group": "^4.4.6", - "clsx": "^2.0.0", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-7.18.0.tgz", + "integrity": "sha512-3UJAYtBquc0SzKxEEdM68XlKOuuCl70ktZPqqI3z4wTZ0HK445XXc32t/s0VPIL94kRxWQcGPpgWFauScDwhug==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6", + "@mui/x-internals": "7.18.0", + "@types/react-transition-group": "^4.4.11", + "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, @@ -1978,16 +1977,52 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", - "@mui/base": "^5.0.0-alpha.87", - "@mui/material": "^5.8.6", - "@mui/system": "^5.8.0", + "@mui/material": "^5.15.14 || ^6.0.0", + "@mui/system": "^5.15.14 || ^6.0.0", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-tree-view/node_modules/@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/@nodelib/fs.scandir": { @@ -2025,6 +2060,16 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/core": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", @@ -2038,9 +2083,9 @@ } }, "node_modules/@plotly/d3": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@plotly/d3/-/d3-3.8.1.tgz", - "integrity": "sha512-x49ThEu1FRA00kTso4Jdfyf2byaCPLBGmLjAYQz5OzaPyLUhHesX3/Nfv2OHEhynhdy2UB39DLXq6thYe2L2kg==" + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@plotly/d3/-/d3-3.8.2.tgz", + "integrity": "sha512-wvsNmh1GYjyJfyEBPKJLTMzgf2c2bEbSIL50lmqVUi+o1NHaLPi1Lb4v7VxXXJn043BhNyrxUrWI85Q+zmjOVA==" }, "node_modules/@plotly/d3-sankey": { "version": "0.7.2", @@ -2063,6 +2108,38 @@ "elementary-circuits-directed-graph": "^1.0.4" } }, + "node_modules/@plotly/mapbox-gl": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@plotly/mapbox-gl/-/mapbox-gl-1.13.4.tgz", + "integrity": "sha512-sR3/Pe5LqT/fhYgp4rT4aSFf1rTsxMbGiH6Hojc7PH36ny5Bn17iVFUjpzycafETURuFbLZUfjODO8LvSI+5zQ==", + "dependencies": { + "@mapbox/geojson-rewind": "^0.5.2", + "@mapbox/geojson-types": "^1.0.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/mapbox-gl-supported": "^1.5.0", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^1.1.1", + "@mapbox/unitbezier": "^0.0.0", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "csscolorparser": "~1.0.3", + "earcut": "^2.2.2", + "geojson-vt": "^3.2.1", + "gl-matrix": "^3.2.1", + "grid-index": "^1.1.0", + "murmurhash-js": "^1.0.0", + "pbf": "^3.2.1", + "potpack": "^1.0.1", + "quickselect": "^2.0.0", + "rw": "^1.3.3", + "supercluster": "^7.1.0", + "tinyqueue": "^2.0.3", + "vt-pbf": "^3.1.1" + }, + "engines": { + "node": ">=6.4.0" + } + }, "node_modules/@plotly/point-cluster": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/@plotly/point-cluster/-/point-cluster-3.1.9.tgz", @@ -2081,9 +2158,9 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.25", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true }, "node_modules/@popperjs/core": { @@ -2128,9 +2205,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", - "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.5.tgz", + "integrity": "sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==", "cpu": [ "arm" ], @@ -2141,9 +2218,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", - "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.5.tgz", + "integrity": "sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==", "cpu": [ "arm64" ], @@ -2154,9 +2231,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", - "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.5.tgz", + "integrity": "sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==", "cpu": [ "arm64" ], @@ -2167,9 +2244,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", - "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.5.tgz", + "integrity": "sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==", "cpu": [ "x64" ], @@ -2180,9 +2257,22 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", - "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.5.tgz", + "integrity": "sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.5.tgz", + "integrity": "sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==", "cpu": [ "arm" ], @@ -2193,9 +2283,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", - "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.5.tgz", + "integrity": "sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==", "cpu": [ "arm64" ], @@ -2206,9 +2296,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", - "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.5.tgz", + "integrity": "sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==", "cpu": [ "arm64" ], @@ -2218,10 +2308,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.5.tgz", + "integrity": "sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", - "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.5.tgz", + "integrity": "sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==", "cpu": [ "riscv64" ], @@ -2231,10 +2334,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.5.tgz", + "integrity": "sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", - "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.5.tgz", + "integrity": "sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==", "cpu": [ "x64" ], @@ -2245,9 +2361,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", - "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.5.tgz", + "integrity": "sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==", "cpu": [ "x64" ], @@ -2258,9 +2374,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", - "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.5.tgz", + "integrity": "sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==", "cpu": [ "arm64" ], @@ -2271,9 +2387,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", - "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.5.tgz", + "integrity": "sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==", "cpu": [ "ia32" ], @@ -2284,9 +2400,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", - "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.5.tgz", + "integrity": "sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==", "cpu": [ "x64" ], @@ -2296,956 +2412,452 @@ "win32" ] }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "node_modules/@sphinxxxx/color-conversion": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz", "integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==" }, "node_modules/@swagger-api/apidom-ast": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-0.93.0.tgz", - "integrity": "sha512-iGrhEXdlgFEQYX4bAootcX+FaeLXruoJnHCFTO6IQ7yKlml3QIl1G9l2KwTzHybHQ70u3nfgE3ovLGOiy8NM5g==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-1.0.0-alpha.9.tgz", + "integrity": "sha512-SAOQrFSFwgDiI4QSIPDwAIJEb4Za+8bu45sNojgV3RMtCz+n4Agw66iqGsDib5YSI/Cg1h4AKFovT3iWdfGWfw==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-error": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", "unraw": "^3.0.0" } }, - "node_modules/@swagger-api/apidom-ast/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ast/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, - "node_modules/@swagger-api/apidom-core": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-0.93.0.tgz", - "integrity": "sha512-OxbLBcnJQ8seFmeKqM2KDMkLJox0YTEhnLq3DnCyvOXnzVHdau+wNIhYSUc1+ZzrjsWqJLU0ntS3LEPb7ttnGw==", + "node_modules/@swagger-api/apidom-core": { + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-1.0.0-alpha.9.tgz", + "integrity": "sha512-vGl8BWRf6ODl39fxElcIOjRE2QG5AJhn8tTNMqjjHB/2WppNBuxOVStYZeVJoWfK03OPK8v4Fp/TAcaP9+R7DQ==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@types/ramda": "~0.29.6", + "@swagger-api/apidom-ast": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", "minim": "~0.23.8", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", "short-unique-id": "^5.0.2", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-core/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-core/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "ts-mixer": "^6.0.3" } }, "node_modules/@swagger-api/apidom-error": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-0.93.0.tgz", - "integrity": "sha512-vJiG0IZS8lOhXn8ZPSsKMh0mun6lOB7m4I8Ju6XeWR0khB7dbp15PAtk6xiFjekbWDa7hPn9584hp0YqXb6p5Q==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-1.0.0-alpha.9.tgz", + "integrity": "sha512-FU/2sFSgsICB9HYFELJ79caRpXXzlAV41QTHsAM46WfRehbzZUQpOBQm4jRi3qJGSa/Jk+mQ7Vt8HLRFMpJFfg==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7" } }, "node_modules/@swagger-api/apidom-json-pointer": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-0.93.0.tgz", - "integrity": "sha512-DnZb/xNKzgBtjKk+5KFMEp5olCeH1wEHbx1YaNY4DDRRtnafphtMxd5/xmapWKj7Glfjfswxi3Uo4m/FAasKPA==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-1.0.0-alpha.9.tgz", + "integrity": "sha512-/W8Ktbgbs29zdhed6KHTFk0qmuIRbvEFi8wu2MHGQ5UT4i99Bdu2OyUiayhnpejWztfQxDgL08pjrQPEwgY8Yg==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-json-pointer/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-json-pointer/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-ns-api-design-systems": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-0.93.0.tgz", - "integrity": "sha512-f3RcUBmZjqmADubnV+yslvtbOJGV3jeMpQuzM9ByS3ASVg+XU1YxKkH5em8BcW3SDj0lqDiQ2ggA9kfPLSuV8A==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-1.0.0-alpha.9.tgz", + "integrity": "sha512-aduC2vbwGgn6ia9IkKpqBYBaKyIDGM/80M3oU3DFgaYIIwynzuwVpN1TkBOLIFy3mAzkWoYKUS0jdZJhMy/6Ug==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", "ts-mixer": "^6.0.3" } }, - "node_modules/@swagger-api/apidom-ns-api-design-systems/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-api-design-systems/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, "node_modules/@swagger-api/apidom-ns-asyncapi-2": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-0.93.0.tgz", - "integrity": "sha512-cEAFsVo/CiPFlw9FAeu/9WR6WixQKxH50SHNvmy8OsCOgYcl5VHF06majZTFCrgZlpCNXPJh9m5A2pUoHtxxUw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-1.0.0-alpha.9.tgz", + "integrity": "sha512-hZjxXJgMt517ADnAauWJh01k7WNRwkbWT5p6b7AXF2H3tl549A2hhLnIg3BBSE3GwB3Nv25GyrI3aA/1dFVC8A==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-json-schema-draft-7": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-asyncapi-2/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-asyncapi-2/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-json-schema-draft-7": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.3" } }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-4": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-0.93.0.tgz", - "integrity": "sha512-dBY7LHrWZ+ydsgD00fQtRq/wOAZjdUh2+PE7/Xe3tYPeD1tv3DZ4F1tcVQeiyGBskF7vReUxUwnQo4uPJipPzA==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-1.0.0-alpha.9.tgz", + "integrity": "sha512-OfX4UBb08C0xD5+F80dQAM2yt5lXxcURWkVEeCwxz7i23BB3nNEbnZXNV91Qo9eaJflPh8dO9iiHQxvfw5IgSg==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.93.0", - "@swagger-api/apidom-core": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-4/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-4/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-ast": "^1.0.0-alpha.9", + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.4" } }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-6": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-0.93.0.tgz", - "integrity": "sha512-u0e0Nq9nuuZyGoOCEjVQJKe5NdsIWezH+q8ev3dABlUNEiWMbtFLS9TvHFBeU11plCsyxjJyYRg8TjnI2Q8xzQ==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-1.0.0-alpha.9.tgz", + "integrity": "sha512-qzUVRSSrnlYGMhK6w57o/RboNvy1FO0iFgEnTk56dD4wN49JRNuFqKI18IgXc1W2r9tTTG70nG1khe4cPE8TNg==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-6/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-6/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.4" } }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-7": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-0.93.0.tgz", - "integrity": "sha512-NkHhyezG5ghx5FhclbIzCwo1wH4gmI8KwMnEuorsXJhanmnkl+JXzDSrpCM3Orvezl+4DEnBeMLyLfbnQMMknw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-1.0.0-alpha.9.tgz", + "integrity": "sha512-Zml8Z8VCckdFjvTogaec1dabd85hg1+xZDseWcCuD0tYkaTY/sZ8zzI0dz6/4HsKCb58qjiWSa0w60N8Syr6WQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@swagger-api/apidom-ns-json-schema-draft-6": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-7/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-7/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-json-schema-draft-6": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.4" } }, "node_modules/@swagger-api/apidom-ns-openapi-2": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-0.93.0.tgz", - "integrity": "sha512-sUZgGyuraLP7rarBp8CISdDLuO8n8L9Q+G8XMiYgl53HGRUY5a7HSGnybcQPpyNPQSNTFKigytSjvsSu8h33ZQ==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-1.0.0-alpha.9.tgz", + "integrity": "sha512-WUZxt7Gs7P4EQsGtoD6cKAjf0uDJhkUxsIW9Bb4EAgO6tdp7LlXhbJ0fJ2QycCLY717SfJbvGLfhuSfTYo4Iow==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-2/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-2/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.3" } }, "node_modules/@swagger-api/apidom-ns-openapi-3-0": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-0.93.0.tgz", - "integrity": "sha512-zmyMUg9+BocHxJuNbUmJCYi/ArOv38Am3/oSkh/5+ANAYOzB1O+ukVvdy7pHDxfZId6KRiP9ZWW6M7VBxz/t/g==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-1.0.0-alpha.9.tgz", + "integrity": "sha512-7ra5uoZGrfCn1LabfJLueChPcYXyg24//LCYBtjTstyueqd5Vp7JCPeP5NnJSAaqVAP47r8ygceBPoxNp9k1EQ==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-3-0/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-3-0/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.3" } }, "node_modules/@swagger-api/apidom-ns-openapi-3-1": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-0.93.0.tgz", - "integrity": "sha512-kUkdcNmJloqqhvEDIAGvamyh1fQrITKGFUqRj5v0YWch/hKrfYk61eHG7igWxnVv3r/wDdM9T3uDWlBefMsj1g==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-1.0.0-alpha.9.tgz", + "integrity": "sha512-nQOwNQgf0C8EVjf2loAAl4ifRuVOdcqycvXUdcTpsUfHN3fbndR8IKpb26mQNmnACmqgmX+LkbMdW9b+K6089g==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.93.0", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-3-1/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-3-1/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-ast": "^1.0.0-alpha.9", + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-json-pointer": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.3" } }, "node_modules/@swagger-api/apidom-ns-workflows-1": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-workflows-1/-/apidom-ns-workflows-1-0.93.0.tgz", - "integrity": "sha512-dL92YBMULuI6HiuOVnB24ozOp4P02xN6Zw8tWzTm/H/W5EWVdso8krq5utjuSTFcurj4rODkPQxY8WRKuIuMDw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-workflows-1/-/apidom-ns-workflows-1-1.0.0-alpha.9.tgz", + "integrity": "sha512-yKo0p8OkQmDib93Kt1yqWmI7JsD6D9qUHxr/SCuAmNNWny1hxm7cZGoKJwJlGd0uAg84j4vmzWOlG3AsJbnT8g==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-workflows-1/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-ns-workflows-1/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", + "ts-mixer": "^6.0.3" } }, "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-0.93.0.tgz", - "integrity": "sha512-lKaSt9YOXbhiBMTJcSCIF0C1fjyWLxKrTWkvbFwwqCcjeMt5vg8N/0nKqQeQm4mcZ946mqnssRVpPbJfWEoIWA==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-1.0.0-alpha.9.tgz", + "integrity": "sha512-xfVMR4HrTzXU0HB4TtxwkNbUIa/cQrPa0BWutJZ0fMYMAtUox2s8GsFYnJfZP52XfpSHFM1VPclivorZqET14g==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-api-design-systems": "^0.93.0", - "@swagger-api/apidom-parser-adapter-json": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-api-design-systems": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-0.93.0.tgz", - "integrity": "sha512-fjIQs0vRP/46M8kwQ3UGpq8piMboIXvrJqu1lDTylS5PYzE9qXpx1BhESZPtBwuoR9kvVYbumlD+BgjCuyzc8g==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-1.0.0-alpha.9.tgz", + "integrity": "sha512-lJZkrhZ8qRTtc5fSLKefCv8j7Xzo8UBfMjpqTJhmETAtU8YfVV2i2znjgxJpm0QwV6FVQqGfK1+ASZQWPLiVcA==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-api-design-systems": "^0.93.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-api-design-systems": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-0.93.0.tgz", - "integrity": "sha512-65Io5+Zy5LBJTvRt3yKBXXfk5M/DCq3mDUSiVcZuyRPHGNi9ViMTdEFCH3rzF0x2v0omG+6OqryndIBVAXEo/g==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-1.0.0-alpha.9.tgz", + "integrity": "sha512-65nmKdPzw4C1bmtYn+3zoxXCI6Gnobr0StI9XE0YWiK+lpso7RH3Cgyl1yPZ0DBRVGzP+Fn9FVzmDNulEfR95w==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-asyncapi-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-json": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-0.93.0.tgz", - "integrity": "sha512-WwGH6StA7kplkTAaV43MziJeJonnJCW6pBOp1bwoEhGaeYO/Yd/dpoFZVDfxAnXJYmDnzk7pqjJm3U6A9BCPcw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-1.0.0-alpha.9.tgz", + "integrity": "sha512-RLI4FpVB3vB6mIuT77yrsv5V2LMZ80dW9XpV+Fmbd4Jkdj+ysAFwT38cI4AsUMOxixpTDIXY1oWD7AjvylHhQQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-asyncapi-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-json": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-0.93.0.tgz", - "integrity": "sha512-FNA36GAqG1EMErkRhMFb4GeW8fuYdzRkOwQmTLWZfKIUzLYOvVMbki8R2dE8ruNs/Gf5VhiQH85mLaCyLwp3xw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-1.0.0-alpha.9.tgz", + "integrity": "sha512-aOewp8/3zobf/O+5Jx8y7+bX3BPRfRlHIv15qp4YVTsLs6gLISWSzTO9JpWe9cR+AfhpsAalFq4t1LwIkmLk4A==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.93.0", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", + "@swagger-api/apidom-ast": "^1.0.0-alpha.9", + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", "tree-sitter": "=0.20.4", - "tree-sitter-json": "=0.20.1", + "tree-sitter-json": "=0.20.2", "web-tree-sitter": "=0.20.3" } }, - "node_modules/@swagger-api/apidom-parser-adapter-json/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-json/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-0.93.0.tgz", - "integrity": "sha512-bBEYiZdiYQQoubZVdkHw3I/qwgI3nvCcrbFAlqELvpFgRZywJzXssxqHqFOR8clvoX8+JVYx5E/MgSC6Rn77uQ==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-1.0.0-alpha.9.tgz", + "integrity": "sha512-zgtsAfkplCFusX2P/saqdn10J8P3kQizCXxHLvxd2j0EhMJk2wfu4HYN5Pej/7/qf/OR1QZxqtacwebd4RfpXA==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-json": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-2": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-0.93.0.tgz", - "integrity": "sha512-UlM924syGaSa5c35OuDC614xBsjIm5DaWUqshFf6DmmP5iDZFQUh0cyIfLDD5/n1wZvAtiIL040zwfTBrK0Udw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-1.0.0-alpha.9.tgz", + "integrity": "sha512-iPuHf0cAZSUhSv8mB0FnVgatTc26cVYohgqz2cvjoGofdqoh5KKIfxOkWlIhm+qGuBp71CfZUrPYPRsd0dHgeg==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.93.0", - "@swagger-api/apidom-parser-adapter-json": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-0.93.0.tgz", - "integrity": "sha512-9rqOLv0ip7knvbdmk8hNa1aN/kaeIIoUKdwO6GaMW9eFh2cvIDyriLxp+FwTatnwhlJjWMwp7Mfyv62WT0cfKQ==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-1.0.0-alpha.9.tgz", + "integrity": "sha512-jwkfO7tzZyyrAgok+O9fKFOv1q/5njMb9DBc3D/ZF3ZLTcnEw8uj4V2HkjKxUweH5k8ip/gc8ueKmO/i7p2fng==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-json": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-0.93.0.tgz", - "integrity": "sha512-8laGpR9MrFBsBDmGNSexKdvLvGnr5QnjhqOSqFIViK/WFG+zEpE5SsWyJkCQJE4EJ5IvxVA8BfBrjjUqe0Z5uA==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-1.0.0-alpha.9.tgz", + "integrity": "sha512-jEIDpjbjwFKXQXS/RHJeA4tthsguLoz+nJPYS3AOLfuSiby5QXsKTxgqHXxG/YJqF1xJbZL+5KcF8UyiDePumw==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-2": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-0.93.0.tgz", - "integrity": "sha512-Tf8eX+MzTsCijXbE5lkfF0/wG5VkvCPGg7hZV7ZGYrzQ584R/Z0xkgHEu3Atqu3Ji9XPGP0u6LqWM/wATuWK0A==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-1.0.0-alpha.9.tgz", + "integrity": "sha512-ieJL8dfIF8fmP3uJRNh/duJa3cCIIv6MzUe6o4uPT/oTDroy4qIATvnq9Dq/gtAv6rcPRpA9VhyghJ1DmjKsZQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.93.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-0.93.0.tgz", - "integrity": "sha512-1Yt3SmgV2x5PAV8NeXIztuRWbIMhAU3cs3SIDJlObzFxXitnsf3cVIRrFTNrK28mqhHU3XNVTat5GrGtlJeD8Q==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-1.0.0-alpha.9.tgz", + "integrity": "sha512-EatIH7PZQSNDsRn9ompc62MYzboY7wAkjfYz+2FzBaSA8Vl5/+740qGQj22tu/xhwW4K72aV2NNL1m47QVF7hA==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-workflows-json-1": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-json-1/-/apidom-parser-adapter-workflows-json-1-0.93.0.tgz", - "integrity": "sha512-tUm049GrXtBHoP8rcLTp+yz5EbJkq/stSgHb4nUNyFH00MKtMkP3j3KnXSCQz2w6br5gzv54DDCKwqPAh7IjuA==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-json-1/-/apidom-parser-adapter-workflows-json-1-1.0.0-alpha.9.tgz", + "integrity": "sha512-LylC2cQdAmvR7bXqwMwBt6FHTMVGinwIdI8pjl4EbPT9hCVm1rdED53caTYM4gCm+CJGRw20r4gb9vn3+N6RrA==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-workflows-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-json": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-workflows-json-1/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-workflows-json-1/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-workflows-1": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-workflows-yaml-1": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-yaml-1/-/apidom-parser-adapter-workflows-yaml-1-0.93.0.tgz", - "integrity": "sha512-8knwzutGHH+69061yHY0xUwmMW/wWUP5jjn4CVDctxYS7BYXb9iaH84VuKJRuDm5M5L/C6yJHgdoWo4IHnpVBw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-yaml-1/-/apidom-parser-adapter-workflows-yaml-1-1.0.0-alpha.9.tgz", + "integrity": "sha512-TlA4+1ca33D7fWxO5jKBytSCv86IGI4Lze4JfrawWUXZ5efhi4LiNmW5TrGlZUyvL7yJtZcA4tn3betlj6jVwA==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-ns-workflows-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-workflows-yaml-1/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-workflows-yaml-1/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-ns-workflows-1": "^1.0.0-alpha.9", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-0.93.0.tgz", - "integrity": "sha512-0z/d/t19f78o4CTxtpMMLdi+7js+JNz7s4/WSJXZ0Q0k5O4pEhlARMMEqJXE4qUXxTGnoXbi4sQY9FV/yA5V0Q==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-1.0.0-alpha.9.tgz", + "integrity": "sha512-jSIHEB7lbh+MP3BhYIXFkeivDR01kugXN70e5FskW7oet2TIARsVEPheWKQFSP1U8bUZA4bsp9h9gOQ9xEeErw==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.93.0", - "@swagger-api/apidom-core": "^0.93.0", - "@swagger-api/apidom-error": "^0.93.0", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", + "@swagger-api/apidom-ast": "^1.0.0-alpha.9", + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@swagger-api/apidom-error": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0", "tree-sitter": "=0.20.4", "tree-sitter-yaml": "=0.5.0", "web-tree-sitter": "=0.20.3" } }, - "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "optional": true, - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, "node_modules/@swagger-api/apidom-reference": { - "version": "0.93.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-0.93.0.tgz", - "integrity": "sha512-kii8DqU3v+Fqv4gLi/3pTEYqR0AhjogcJnJUuKZqs1G/UiGk2RiEN4i/VyJQn0iwL4w4UyFcLOG4kyYxNgDAJw==", + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-1.0.0-alpha.9.tgz", + "integrity": "sha512-KQ6wB5KplqdSsjxdA8BaQulj5zlF5VBCd5KP3RN/9vvixgsD/gyrVY59nisdzmPTqiL6yjhk612eQ96MgG8KiA==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.93.0", - "@types/ramda": "~0.29.6", + "@swagger-api/apidom-core": "^1.0.0-alpha.9", + "@types/ramda": "~0.30.0", "axios": "^1.4.0", "minimatch": "^7.4.3", "process": "^0.11.10", - "ramda": "~0.29.1", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" + "ramda": "~0.30.0", + "ramda-adjunct": "^5.0.0" }, "optionalDependencies": { - "@swagger-api/apidom-error": "^0.93.0", - "@swagger-api/apidom-json-pointer": "^0.93.0", - "@swagger-api/apidom-ns-asyncapi-2": "^0.93.0", - "@swagger-api/apidom-ns-openapi-2": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.93.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.93.0", - "@swagger-api/apidom-ns-workflows-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.93.0", - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.93.0", - "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-json": "^0.93.0", - "@swagger-api/apidom-parser-adapter-openapi-json-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^0.93.0", - "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^0.93.0", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^0.93.0", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-workflows-json-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-workflows-yaml-1": "^0.93.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.93.0" - } - }, - "node_modules/@swagger-api/apidom-reference/node_modules/@types/ramda": { - "version": "0.29.10", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.10.tgz", - "integrity": "sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==", - "dependencies": { - "types-ramda": "^0.29.7" - } - }, - "node_modules/@swagger-api/apidom-reference/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" + "@swagger-api/apidom-error": "^1.0.0-alpha.1", + "@swagger-api/apidom-json-pointer": "^1.0.0-alpha.1", + "@swagger-api/apidom-ns-asyncapi-2": "^1.0.0-alpha.1", + "@swagger-api/apidom-ns-openapi-2": "^1.0.0-alpha.1", + "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-alpha.1", + "@swagger-api/apidom-ns-openapi-3-1": "^1.0.0-alpha.1", + "@swagger-api/apidom-ns-workflows-1": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-json": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-openapi-json-2": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-workflows-json-1": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-workflows-yaml-1": "^1.0.0-alpha.1", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^1.0.0-alpha.1" } }, "node_modules/@swagger-api/apidom-reference/node_modules/minimatch": { @@ -3262,24 +2874,15 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@swagger-api/apidom-reference/node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, "node_modules/@swc/core": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.106.tgz", - "integrity": "sha512-++QPSPkFq2qELYVScxNHJC42hKQChjiTWS2P0QQ5JWT4NHb9lmNSfrc1ylFIyImwRnxsW2MTBALLYLf95EFAsg==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.26.tgz", + "integrity": "sha512-f5uYFf+TmMQyYIoxkn/evWhNGuUzC730dFwAKGwBVHHVoPyak1/GvJUm6i1SKl+2Hrj9oN0i3WSoWWZ4pgI8lw==", "dev": true, "hasInstallScript": true, "dependencies": { - "@swc/counter": "^0.1.1", - "@swc/types": "^0.1.5" + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" }, "engines": { "node": ">=10" @@ -3289,19 +2892,19 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.106", - "@swc/core-darwin-x64": "1.3.106", - "@swc/core-linux-arm-gnueabihf": "1.3.106", - "@swc/core-linux-arm64-gnu": "1.3.106", - "@swc/core-linux-arm64-musl": "1.3.106", - "@swc/core-linux-x64-gnu": "1.3.106", - "@swc/core-linux-x64-musl": "1.3.106", - "@swc/core-win32-arm64-msvc": "1.3.106", - "@swc/core-win32-ia32-msvc": "1.3.106", - "@swc/core-win32-x64-msvc": "1.3.106" + "@swc/core-darwin-arm64": "1.7.26", + "@swc/core-darwin-x64": "1.7.26", + "@swc/core-linux-arm-gnueabihf": "1.7.26", + "@swc/core-linux-arm64-gnu": "1.7.26", + "@swc/core-linux-arm64-musl": "1.7.26", + "@swc/core-linux-x64-gnu": "1.7.26", + "@swc/core-linux-x64-musl": "1.7.26", + "@swc/core-win32-arm64-msvc": "1.7.26", + "@swc/core-win32-ia32-msvc": "1.7.26", + "@swc/core-win32-x64-msvc": "1.7.26" }, "peerDependencies": { - "@swc/helpers": "^0.5.0" + "@swc/helpers": "*" }, "peerDependenciesMeta": { "@swc/helpers": { @@ -3310,9 +2913,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.106.tgz", - "integrity": "sha512-XYcbViNyHnnm7RWOAO1YipMmthM7m2aXF32b0y+JMLYFBEyFpjVX9btLkzeL7wRx/5B3I35yJNhE+xyx0Q1Gkw==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.26.tgz", + "integrity": "sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw==", "cpu": [ "arm64" ], @@ -3326,9 +2929,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.106.tgz", - "integrity": "sha512-YKDPhUdfuwhmOUS9+CaIwl/0Tp+f1b73BH2EIESuxSNsogZf18a8HQ8O0fQEwdiwmA5LEqw47cj+kfOWV/0+kw==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.26.tgz", + "integrity": "sha512-az3cibZdsay2HNKmc4bjf62QVukuiMRh5sfM5kHR/JMTrLyS6vSw7Ihs3UTkZjUxkLTT8ro54LI6sV6sUQUbLQ==", "cpu": [ "x64" ], @@ -3342,9 +2945,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.106.tgz", - "integrity": "sha512-bHxxJXogvFfocLL5inZxxtx/x/WgKozigp80Vbx0viac1fPDJrqKBw2X4MzpMiuTRAGVQ03jJI6pDwbSBf+yDw==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.26.tgz", + "integrity": "sha512-VYPFVJDO5zT5U3RpCdHE5v1gz4mmR8BfHecUZTmD2v1JeFY6fv9KArJUpjrHEEsjK/ucXkQFmJ0jaiWXmpOV9Q==", "cpu": [ "arm" ], @@ -3358,9 +2961,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.106.tgz", - "integrity": "sha512-c7jue++CHLgtpeaakEukoCLT9eNrImizbleE9Y7Is8CHqLq/7DG4s+7ma9DFKXIzW2MpTg9byIEQfpqSphVW6A==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.26.tgz", + "integrity": "sha512-YKevOV7abpjcAzXrhsl+W48Z9mZvgoVs2eP5nY+uoMAdP2b3GxC0Df1Co0I90o2lkzO4jYBpTMcZlmUXLdXn+Q==", "cpu": [ "arm64" ], @@ -3374,9 +2977,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.106.tgz", - "integrity": "sha512-51EaC3Q8qAhLtWVnAVqoYX/gk3tK31cCBzUpwCcmhianhEBM2/WtKRAS4MqPhE8VVZuN3WjO2c2JaF2mX0yuoA==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.26.tgz", + "integrity": "sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg==", "cpu": [ "arm64" ], @@ -3390,9 +2993,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.106.tgz", - "integrity": "sha512-tOUi8BB6jAeCXgx7ESLNnX7nrbMVKQ/XajK77v7Ad4SXf9HYArnimBJpXUUyVFJTXLSv4e6c7s6XHHqXb5Lwcg==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.26.tgz", + "integrity": "sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w==", "cpu": [ "x64" ], @@ -3406,9 +3009,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.106.tgz", - "integrity": "sha512-binLw4Lbd83NPy4/m/teH2nbaifxveSD+sKDvpxywRbvYW2I0w/iCBpUBcbnl16TQF4TPOGpq5YwG9lVxPVw5g==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.26.tgz", + "integrity": "sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ==", "cpu": [ "x64" ], @@ -3422,9 +3025,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.106.tgz", - "integrity": "sha512-n4ttBWr8tM7DPzwcEOIBTyTMHZTzCmbic/HTtxEsPyMAf/Daen+yrTKzjPP6k2usfSrjkxA780RSJJxI1N8r2w==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.26.tgz", + "integrity": "sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA==", "cpu": [ "arm64" ], @@ -3438,9 +3041,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.106.tgz", - "integrity": "sha512-GhDNIwxE5FhkujESI6h/4ysT3wxwmrzTUlZYaR8rRui6a6SdX9feIPUHPEE5o5hpyp+xqlmvRxKkRxOnwsq8iA==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.26.tgz", + "integrity": "sha512-9YngxNcG3177GYdsTum4V98Re+TlCeJEP4kEwEg9EagT5s3YejYdKwVAkAsJszzkXuyRDdnHUpYbTrPG6FiXrQ==", "cpu": [ "ia32" ], @@ -3454,9 +3057,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.106", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.106.tgz", - "integrity": "sha512-2M6yWChuMS1+/MPo3Dor0SOMkvmiugonWlzsZBAu/oZboH2xKrHSRv7brsBujb2Oe47r+NsbV+vq9tnnP9Vl1Q==", + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.26.tgz", + "integrity": "sha512-VR+hzg9XqucgLjXxA13MtV5O3C0bK0ywtLIBw/+a+O+Oc6mxFWHtdUeXDbIi5AiPbn0fjgVJMqYnyjGyyX8u0w==", "cpu": [ "x64" ], @@ -3470,38 +3073,41 @@ } }, "node_modules/@swc/counter": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", - "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", "dev": true }, "node_modules/@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } }, "node_modules/@tanstack/match-sorter-utils": { - "version": "8.8.4", - "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz", - "integrity": "sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==", + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.19.4.tgz", + "integrity": "sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==", "dependencies": { - "remove-accents": "0.4.2" + "remove-accents": "0.5.0" }, "engines": { "node": ">=12" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/kentcdodds" + "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/react-table": { - "version": "8.10.7", - "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.10.7.tgz", - "integrity": "sha512-bXhjA7xsTcsW8JPTTYlUg/FuBpn8MNjiEPhkNhIGCUR6iRQM2+WEco4OBpvDeVcR9SE+bmWLzdfiY7bCbCSVuA==", + "version": "8.20.5", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz", + "integrity": "sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==", "dependencies": { - "@tanstack/table-core": "8.10.7" + "@tanstack/table-core": "8.20.5" }, "engines": { "node": ">=12" @@ -3511,16 +3117,16 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" + "react": ">=16.8", + "react-dom": ">=16.8" } }, "node_modules/@tanstack/react-virtual": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.0.1.tgz", - "integrity": "sha512-IFOFuRUTaiM/yibty9qQ9BfycQnYXIDHGP2+cU+0LrFFGNhVxCXSQnaY6wkX8uJVteFEBjUondX0Hmpp7TNcag==", + "version": "3.10.6", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.10.6.tgz", + "integrity": "sha512-xaSy6uUxB92O8mngHZ6CvbhGuqxQ5lIZWCBy+FjhrbHmOwc6BnOnKkYm2FsB1/BpKw/+FVctlMbEtI+F6I1aJg==", "dependencies": { - "@tanstack/virtual-core": "3.0.0" + "@tanstack/virtual-core": "3.10.6" }, "funding": { "type": "github", @@ -3532,9 +3138,9 @@ } }, "node_modules/@tanstack/table-core": { - "version": "8.10.7", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.10.7.tgz", - "integrity": "sha512-KQk5OMg5OH6rmbHZxuNROvdI+hKDIUxANaHlV+dPlNN7ED3qYQ/WkpY2qlXww1SIdeMlkIhpN/2L00rof0fXFw==", + "version": "8.20.5", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz", + "integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==", "engines": { "node": ">=12" }, @@ -3544,18 +3150,18 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.0.0.tgz", - "integrity": "sha512-SYXOBTjJb05rXa2vl55TTwO40A6wKu0R5i1qQwhJYNDIqaIGF7D0HsLw+pJAyi2OvntlEIVusx3xtbbgSUi6zg==", + "version": "3.10.6", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.10.6.tgz", + "integrity": "sha512-1giLc4dzgEKLMx5pgKjL6HlG5fjZMgCjzlKAlpr7yoUtetVPELgER1NtephAI910nMwfPTHNyWKSFmJdHkz2Cw==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@testing-library/dom": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", - "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "dev": true, "peer": true, "dependencies": { @@ -3573,48 +3179,88 @@ } }, "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@testing-library/dom/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "peer": true, "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@testing-library/dom/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "peer": true }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@testing-library/jest-dom": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.6.tgz", - "integrity": "sha512-8qpnGVincVDLEcQXWaHOf6zmlbwTKc6Us6PPu4CRnPXCzo2OGBS5cwgMMOWdxDpEz1mkbvXHpEy99M5Yvt682w==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", + "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", "dev": true, "dependencies": { "@adobe/css-tools": "^4.4.0", - "@babel/runtime": "^7.9.2", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", @@ -3626,30 +3272,21 @@ "node": ">=14", "npm": ">=6", "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" }, - "peerDependencies": { - "@jest/globals": ">= 28", - "@types/bun": "latest", - "@types/jest": ">= 28", - "jest": ">= 28", - "vitest": ">= 0.32" + "engines": { + "node": ">=8" }, - "peerDependenciesMeta": { - "@jest/globals": { - "optional": true - }, - "@types/bun": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "jest": { - "optional": true - }, - "vitest": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/@testing-library/jest-dom/node_modules/chalk": { @@ -3665,16 +3302,55 @@ "node": ">=8" } }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", "dev": true }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@testing-library/react": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", - "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz", + "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.5" @@ -3712,61 +3388,72 @@ } }, "node_modules/@total-typescript/ts-reset": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@total-typescript/ts-reset/-/ts-reset-0.5.1.tgz", - "integrity": "sha512-AqlrT8YA1o7Ff5wPfMOL0pvL+1X+sw60NN6CcOCqs658emD6RfiXhF7Gu9QcfKBH7ELY2nInLhKSCWVoNL70MQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@total-typescript/ts-reset/-/ts-reset-0.6.1.tgz", + "integrity": "sha512-cka47fVSo6lfQDIATYqb/vO1nvFfbPw7uWLayIXIhGETj0wcOOlrlkobOMDNQOFr9QOafegUPq13V2+6vtD7yg==", "dev": true }, "node_modules/@turf/area": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@turf/area/-/area-6.5.0.tgz", - "integrity": "sha512-xCZdiuojokLbQ+29qR6qoMD89hv+JAgWjLrwSEWL+3JV8IXKeNFl6XkEJz9HGkVpnXvQKJoRz4/liT+8ZZ5Jyg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/area/-/area-7.1.0.tgz", + "integrity": "sha512-w91FEe02/mQfMPRX2pXua48scFuKJ2dSVMF2XmJ6+BJfFiCPxp95I3+Org8+ZsYv93CDNKbf0oLNEPnuQdgs2g==", "dependencies": { - "@turf/helpers": "^6.5.0", - "@turf/meta": "^6.5.0" + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" }, "funding": { "url": "https://opencollective.com/turf" } }, "node_modules/@turf/bbox": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-6.5.0.tgz", - "integrity": "sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-7.1.0.tgz", + "integrity": "sha512-PdWPz9tW86PD78vSZj2fiRaB8JhUHy6piSa/QXb83lucxPK+HTAdzlDQMTKj5okRCU8Ox/25IR2ep9T8NdopRA==", "dependencies": { - "@turf/helpers": "^6.5.0", - "@turf/meta": "^6.5.0" + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" }, "funding": { "url": "https://opencollective.com/turf" } }, "node_modules/@turf/centroid": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-6.5.0.tgz", - "integrity": "sha512-MwE1oq5E3isewPprEClbfU5pXljIK/GUOMbn22UM3IFPDJX0KeoyLNwghszkdmFp/qMGL/M13MMWvU+GNLXP/A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.1.0.tgz", + "integrity": "sha512-1Y1b2l+ZB1CZ+ITjUCsGqC4/tSjwm/R4OUfDztVqyyCq/VvezkLmTNqvXTGXgfP0GXkpv68iCfxF5M7QdM5pJQ==", "dependencies": { - "@turf/helpers": "^6.5.0", - "@turf/meta": "^6.5.0" + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" }, "funding": { "url": "https://opencollective.com/turf" } }, "node_modules/@turf/helpers": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz", - "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.1.0.tgz", + "integrity": "sha512-dTeILEUVeNbaEeoZUOhxH5auv7WWlOShbx7QSd4s0T4Z0/iz90z9yaVCtZOLbU89umKotwKaJQltBNO9CzVgaQ==", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, "funding": { "url": "https://opencollective.com/turf" } }, "node_modules/@turf/meta": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.5.0.tgz", - "integrity": "sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.1.0.tgz", + "integrity": "sha512-ZgGpWWiKz797Fe8lfRj7HKCkGR+nSJ/5aKXMyofCvLSc2PuYJs/qyyifDPWjASQQCzseJ7AlF2Pc/XQ/3XkkuA==", "dependencies": { - "@turf/helpers": "^6.5.0" + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10" }, "funding": { "url": "https://opencollective.com/turf" @@ -4046,18 +3733,18 @@ } }, "node_modules/@types/debug": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", - "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, "dependencies": { "@types/ms": "*" } }, "node_modules/@types/draft-convert": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/draft-convert/-/draft-convert-2.1.5.tgz", - "integrity": "sha512-gRJphK0P4yl/Px5iVZXJFB5ojq4aF91QL77vR0lBth9w66dnceOFn5lj3WoKdr5fXIaPKQoA4JRxRtdNoAr1TQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@types/draft-convert/-/draft-convert-2.1.8.tgz", + "integrity": "sha512-gzHXLnOhDqdDv3ieMCZjqbmP992MBBn1u9HrhrCQ4+sip2pFz7d+fXL4GqaBgFjM/A5+iSNRhkr4ZP4tMR3jWw==", "dev": true, "dependencies": { "@types/draft-js": "*", @@ -4065,9 +3752,9 @@ } }, "node_modules/@types/draft-js": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.11.13.tgz", - "integrity": "sha512-4cMlNWoKwcRwkA+GtCD53u5Dj78n9Z8hScB5rZYKw4Q3UZxh0h1Fm4ezLgGjAHkhsdrviWQm3MPuUi/jLOuq8A==", + "version": "0.11.18", + "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.11.18.tgz", + "integrity": "sha512-lP6yJ+EKv5tcG1dflWgDKeezdwBa8wJ7KkiNrrHqXuXhl/VGes1SKjEfKHDZqOz19KQbrAhFvNhDPWwnQXYZGQ==", "dev": true, "dependencies": { "@types/react": "*", @@ -4075,30 +3762,36 @@ } }, "node_modules/@types/draftjs-to-html": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@types/draftjs-to-html/-/draftjs-to-html-0.8.2.tgz", - "integrity": "sha512-bjxcYNJJ7RTvYFx+P557aHs8TIVqqzJsl1kkxt4r9r+StxIdsTcrHZ2fhGKJ+jZRLsD5o+LReDFGeqzNghrGHQ==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/@types/draftjs-to-html/-/draftjs-to-html-0.8.4.tgz", + "integrity": "sha512-5FZcjFoJL57N/IttLCTCNI0krX+181oCl5hf76u3TqPkqBAphHrJAO9ReYesx9138kcObaYmpnWC2Yrqxoqd2Q==", "dev": true, "dependencies": { "@types/draft-js": "*" } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/geojson": { - "version": "7946.0.13", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.13.tgz", - "integrity": "sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ==", - "dev": true + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, + "node_modules/@types/geojson-vt": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/geojson-vt/-/geojson-vt-3.2.5.tgz", + "integrity": "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==", + "dependencies": { + "@types/geojson": "*" + } }, "node_modules/@types/hast": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.9.tgz", - "integrity": "sha512-pTHyNlaMD/oKJmS+ZZUyFUcsZeBZpC0lmGquw98CqRVNgAdJZJeD7GoeLiT6Xbx5rU9VCjSt0RwEvDgzh4obFw==", + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", "dependencies": { "@types/unist": "^2" } @@ -4113,16 +3806,15 @@ } }, "node_modules/@types/js-cookie": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.4.tgz", - "integrity": "sha512-vMMnFF+H5KYqdd/myCzq6wLDlPpteJK+jGFgBus3Da7lw+YsDmx2C8feGTzY2M3Fo823yON+HC2CL240j4OV+w==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/jsoneditor": { "version": "9.9.5", @@ -4135,11 +3827,26 @@ } }, "node_modules/@types/lodash": { - "version": "4.14.199", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", - "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", + "version": "4.17.9", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz", + "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==", "dev": true }, + "node_modules/@types/mapbox__point-geometry": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz", + "integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==" + }, + "node_modules/@types/mapbox__vector-tile": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz", + "integrity": "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==", + "dependencies": { + "@types/geojson": "*", + "@types/mapbox__point-geometry": "*", + "@types/pbf": "*" + } + }, "node_modules/@types/ms": { "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", @@ -4147,16 +3854,23 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.16.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz", - "integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==", - "dev": true + "version": "22.7.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.3.tgz", + "integrity": "sha512-qXKfhXXqGTyBskvWEzJZPUxSslAiLaB6JGP1ic/XTH9ctGgzdgYguuLP1C601aRTSDNlLb0jbKqXjZ48GNraSA==", + "dependencies": { + "undici-types": "~6.19.2" + } }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, + "node_modules/@types/pbf": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz", + "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" + }, "node_modules/@types/pikaday": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/@types/pikaday/-/pikaday-1.7.4.tgz", @@ -4166,48 +3880,46 @@ } }, "node_modules/@types/plotly.js": { - "version": "2.12.32", - "resolved": "https://registry.npmjs.org/@types/plotly.js/-/plotly.js-2.12.32.tgz", - "integrity": "sha512-pCE60W1v77zxobnA1oGIisHhGzTHv8c4fAtM81Y1h7gezeKpLpx4E0fQ3ThKIPOIvGlnoVseUjSpFwFqIKdsXg==", + "version": "2.33.4", + "resolved": "https://registry.npmjs.org/@types/plotly.js/-/plotly.js-2.33.4.tgz", + "integrity": "sha512-BzAbsJTiUQyALkkYx1D31YZ9YvcU2ag3LlE/iePMo19eDPvM30cbM2EFNIcu31n39EhXj/9G7800XLA8/rfApA==", "dev": true }, "node_modules/@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" }, "node_modules/@types/ramda": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.5.tgz", - "integrity": "sha512-oBBdRfoZoCl/aBIpBbct/uUHAbJ5i7vSOHK83SvH2Qr9ermYITRNKnEYgGJlnkagUY2cu8L2//Jq7o1355Go5A==", - "dev": true, + "version": "0.30.2", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.30.2.tgz", + "integrity": "sha512-PyzHvjCalm2BRYjAU6nIB3TprYwMNOUY/7P/N8bSzp9W/yM2YrtGtAnnVtaCNSeOZ8DzKyFDvaqQs7LnWwwmBA==", "dependencies": { - "types-ramda": "^0.29.4" + "types-ramda": "^0.30.1" } }, "node_modules/@types/react": { - "version": "18.2.24", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.24.tgz", - "integrity": "sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw==", + "version": "18.3.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.9.tgz", + "integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-beautiful-dnd": { - "version": "13.1.5", - "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.5.tgz", - "integrity": "sha512-mzohmMtV48b0bXF2dP8188LzUv9HAGHKucOORYsd5Sqq830pJ4gseFyDDAH0TR4TeD1ceG9DxTQ0FOFbtCSy4Q==", + "version": "13.1.8", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz", + "integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==", "dev": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/react-color": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.7.tgz", - "integrity": "sha512-IGZA7e8Oia0+Sb3/1KP0qTThGelZ9DRspfeLrFWQWv5vXHiYlJJQMC2kgQr75CtP4uL8/kvT8qBgrOVlxVoNTw==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.12.tgz", + "integrity": "sha512-pr3uKE3lSvf7GFo1Rn2K3QktiZQFFrSgSGJ/3iMvSOYWt2pPAJ97rVdVfhWxYJZ8prAEXzoP2XX//3qGSQgu7Q==", "dev": true, "dependencies": { "@types/react": "*", @@ -4224,18 +3936,18 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.8", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.8.tgz", - "integrity": "sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "devOptional": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/react-plotly.js": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@types/react-plotly.js/-/react-plotly.js-2.6.1.tgz", - "integrity": "sha512-vFJZRCC2Pav0NdrFm0grPMm9+67ejGZZglDBWqo+J6VFbB4CAatjoNiowfardznuujaaoDNoZ4MSCFwYyVk4aA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/react-plotly.js/-/react-plotly.js-2.6.3.tgz", + "integrity": "sha512-HBQwyGuu/dGXDsWhnQrhH+xcJSsHvjkwfSRjP+YpOsCCWryIuXF78ZCBjpfgO3sCc0Jo8sYp4NOGtqT7Cn3epQ==", "dev": true, "dependencies": { "@types/plotly.js": "*", @@ -4243,9 +3955,9 @@ } }, "node_modules/@types/react-redux": { - "version": "7.1.33", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", - "integrity": "sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==", + "version": "7.1.34", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz", + "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==", "dependencies": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -4253,65 +3965,68 @@ "redux": "^4.0.0" } }, + "node_modules/@types/react-syntax-highlighter": { + "version": "15.5.13", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", + "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", - "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", "dependencies": { "@types/react": "*" } }, "node_modules/@types/react-virtualized-auto-sizer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz", - "integrity": "sha512-GH8sAnBEM5GV9LTeiz56r4ZhMOUSrP43tAQNSRVxNexDjcNKLCEtnxusAItg1owFUFE6k0NslV26gqVClVvong==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.4.tgz", + "integrity": "sha512-nhYwlFiYa8M3S+O2T9QO/e1FQUYMr/wJENUdf/O0dhRi1RS/93rjrYQFYdbUqtdFySuhrtnEDX29P6eKOttY+A==", "dev": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/react-window": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.6.tgz", - "integrity": "sha512-AVJr3A5rIO9dQQu5TwTN0lP2c1RtuqyyZGCt7PGP8e5gUpn1PuQRMJb/u3UpdbwTHh4wbEi33UMW5NI0IXt1Mg==", + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", + "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", "dev": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/reactcss": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.11.tgz", - "integrity": "sha512-0fFy0ubuPlhksId8r9V8nsLcxBAPQnn15g/ERAElgE9L6rOquMj2CapsxqfyBuHlkp0/ndEUVnkYI7MkTtkGpw==", + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.12.tgz", + "integrity": "sha512-BrXUQ86/wbbFiZv8h/Q1/Q1XOsaHneYmCb/tHe9+M8XBAAUc2EHfdY0DY22ZZjVSaXr5ix7j+zsqO2eGZub8lQ==", "dev": true, "dependencies": { "@types/react": "*" } }, - "node_modules/@types/redux-logger": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/redux-logger/-/redux-logger-3.0.10.tgz", - "integrity": "sha512-wjcuptRVZQoWjbwKdLrEnit9A7TvW0HD6ZYNQGWRRCUBBux2RT8JxqwYemaS2fTQT3ebOvsszt2L/Hrylxh5PA==", - "dev": true, - "dependencies": { - "redux": "^4.0.0" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" - }, "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, + "node_modules/@types/supercluster": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", + "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/swagger-ui-react": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-4.18.1.tgz", - "integrity": "sha512-nYhNi+cyN78vve1/QY5PNKYzHYlDKETtXj+gQAhuoCRB+GxGT3MVJUj8WCdwYj4vF0s1j68qkLv/66DGe5ZlnA==", + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-4.18.3.tgz", + "integrity": "sha512-Mo/R7IjDVwtiFPs84pWvh5pI9iyNGBjmfielxqbOh2Jv+8WVSDVe8Nu25kb5BOuV2xmGS3o33jr6nwDJMBcX+Q==", "dev": true, "dependencies": { "@types/react": "*" @@ -4328,9 +4043,9 @@ } }, "node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" }, "node_modules/@types/use-sync-external-store": { "version": "0.0.3", @@ -4338,22 +4053,22 @@ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, "node_modules/@types/uuid": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.4.tgz", - "integrity": "sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.14.0.tgz", - "integrity": "sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.2.0.tgz", + "integrity": "sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/type-utils": "6.14.0", - "@typescript-eslint/utils": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/type-utils": "7.2.0", + "@typescript-eslint/utils": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -4369,8 +4084,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -4378,16 +4093,28 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.14.0.tgz", - "integrity": "sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4" }, "engines": { @@ -4398,7 +4125,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -4407,13 +4134,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz", - "integrity": "sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", + "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0" + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4424,13 +4151,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.14.0.tgz", - "integrity": "sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz", + "integrity": "sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.14.0", - "@typescript-eslint/utils": "6.14.0", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/utils": "7.2.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -4442,7 +4169,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -4451,9 +4178,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.14.0.tgz", - "integrity": "sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", + "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4464,16 +4191,17 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz", - "integrity": "sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", + "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/visitor-keys": "6.14.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -4490,18 +4218,45 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.14.0.tgz", - "integrity": "sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.2.0.tgz", + "integrity": "sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.14.0", - "@typescript-eslint/types": "6.14.0", - "@typescript-eslint/typescript-estree": "6.14.0", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", "semver": "^7.5.4" }, "engines": { @@ -4512,16 +4267,28 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz", - "integrity": "sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", + "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.14.0", + "@typescript-eslint/types": "7.2.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4539,170 +4306,339 @@ "dev": true }, "node_modules/@vitejs/plugin-react-swc": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.5.0.tgz", - "integrity": "sha512-1PrOvAaDpqlCV+Up8RkAh9qaiUjoDUcjtttyhXDKw53XA6Ve16SOp6cCOpRs8Dj8DqUQs6eTW5YkLcLJjrXAig==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.0.tgz", + "integrity": "sha512-yrknSb3Dci6svCd/qhHqhFPDSw0QtjumcqdKMoNNzmOl5lMXTTiqzjWtG4Qask2HdvvzaNgSunbQGet8/GrKdA==", "dev": true, "dependencies": { - "@swc/core": "^1.3.96" + "@swc/core": "^1.5.7" }, "peerDependencies": { "vite": "^4 || ^5" } }, "node_modules/@vitest/coverage-v8": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.6.0.tgz", - "integrity": "sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", + "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.2.1", + "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.4", + "debug": "^4.3.6", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.4", - "istanbul-reports": "^3.1.6", - "magic-string": "^0.30.5", - "magicast": "^0.3.3", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "test-exclude": "^6.0.0" + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.11", + "magicast": "^0.3.4", + "std-env": "^3.7.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "1.6.0" + "@vitest/browser": "2.1.1", + "vitest": "2.1.1" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, "node_modules/@vitest/expect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", - "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", + "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", "dev": true, "dependencies": { - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "chai": "^4.3.10" + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/runner": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", - "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "node_modules/@vitest/mocker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", + "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", "dev": true, "dependencies": { - "@vitest/utils": "1.6.0", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" }, "funding": { "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.1", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "node_modules/@vitest/pretty-format": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", + "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", "dev": true, "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": ">=18" + "tinyrainbow": "^1.2.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/runner/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "node_modules/@vitest/runner": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", + "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", "dev": true, - "engines": { - "node": ">=12.20" + "dependencies": { + "@vitest/utils": "2.1.1", + "pathe": "^1.1.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", - "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", + "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", "dev": true, "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" + "@vitest/pretty-format": "2.1.1", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", - "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", + "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", "dev": true, "dependencies": { - "tinyspy": "^2.2.0" + "tinyspy": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/ui": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.6.0.tgz", - "integrity": "sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-2.1.1.tgz", + "integrity": "sha512-IIxo2LkQDA+1TZdPLYPclzsXukBWd5dX2CKpGqH8CCt8Wh0ZuDn4+vuQ9qlppEju6/igDGzjWF/zyorfsf+nHg==", "dev": true, "dependencies": { - "@vitest/utils": "1.6.0", - "fast-glob": "^3.3.2", - "fflate": "^0.8.1", - "flatted": "^3.2.9", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "sirv": "^2.0.4" + "@vitest/utils": "2.1.1", + "fflate": "^0.8.2", + "flatted": "^3.3.1", + "pathe": "^1.1.2", + "sirv": "^2.0.4", + "tinyglobby": "^0.2.6", + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "1.6.0" + "vitest": "2.1.1" } }, "node_modules/@vitest/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", + "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", "dev": true, "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" + "@vitest/pretty-format": "2.1.1", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, "node_modules/@xobotyi/scrollbar-width": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==" }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "peer": true }, "node_modules/abs-svg-path": { "version": "0.1.1", @@ -4710,15 +4646,14 @@ "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==" }, "node_modules/ace-builds": { - "version": "1.32.3", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.3.tgz", - "integrity": "sha512-ptSTUmDEU+LuwGiPY3/qQPmmAWE27vuv5sASL8swLRyLGJb7Ye7a8MrJ4NnAkFh1sJgVUqKTEGWRRFDmqYPw2Q==" + "version": "1.36.2", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.36.2.tgz", + "integrity": "sha512-eqqfbGwx/GKjM/EnFu4QtQ+d2NNBu84MGgxoG8R5iyFpcVeQ4p9YlTL+ZzdEJqhdkASqoqOxCSNNGyB6lvMm+A==" }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -4726,6 +4661,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -4735,18 +4679,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -4774,6 +4706,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peer": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, "node_modules/almost-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/almost-equal/-/almost-equal-1.1.0.tgz", @@ -4789,19 +4730,21 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, + "node_modules/apg-lite": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/apg-lite/-/apg-lite-1.0.4.tgz", + "integrity": "sha512-B32zCN3IdHIc99Vy7V9BaYTUzLeRA8YXYY1aQD1/5I2aqIrO0coi4t6hJPqMisidlBxhyME8UexkHt31SlR6Og==" + }, "node_modules/are-docs-informative": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", @@ -4825,19 +4768,30 @@ "dequal": "^2.0.3" } }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/array-bounds": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-bounds/-/array-bounds-1.0.1.tgz", "integrity": "sha512-8wdW3ZGk6UjMPJx/glyEt0sLzzwAE1bhToPsO1W2pbpR2gULyxe3BjSiuJFheP50T/GgODVPz2fuMUmIywt8cQ==" }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4852,15 +4806,16 @@ } }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -4897,6 +4852,26 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", @@ -4934,30 +4909,34 @@ } }, "node_modules/array.prototype.tosorted": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -4973,21 +4952,20 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/asynciterator.prototype": { + "node_modules/assign-symbols": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "engines": { + "node": ">=0.10.0" } }, "node_modules/asynckit": { @@ -4995,14 +4973,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/attr-accept": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz", @@ -5020,10 +4990,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -5032,11 +5005,11 @@ } }, "node_modules/axios": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", - "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -5054,14 +5027,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-merge/node_modules/deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -5086,6 +5051,14 @@ "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5138,29 +5111,29 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "funding": [ { "type": "opencollective", @@ -5176,10 +5149,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -5217,16 +5190,21 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/bytewise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", + "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", + "dependencies": { + "bytewise-core": "^1.2.2", + "typewise": "^1.0.3" + } + }, + "node_modules/bytewise-core": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", + "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", + "dependencies": { + "typewise-core": "^1.2" } }, "node_modules/cac": { @@ -5239,13 +5217,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5260,9 +5244,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001636", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", - "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", + "version": "1.0.30001664", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", + "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", "funding": [ { "type": "opencollective", @@ -5292,36 +5276,40 @@ "integrity": "sha512-+VsMpRr64jYgKq2IeFUNel3vCZH/IzS+iXSHxmUV3IUH5dXlC9xHz4AwtPZisDxZ5MWcuK0V+TXgPKFPiZnxzg==" }, "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", "dev": true, "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=12" } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" } }, "node_modules/character-entities": { @@ -5352,15 +5340,12 @@ } }, "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, "engines": { - "node": "*" + "node": ">= 16" } }, "node_modules/chevrotain": { @@ -5378,18 +5363,13 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "optional": true }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "peer": true, "engines": { - "node": ">=8" + "node": ">=6.0" } }, "node_modules/clamp": { @@ -5403,9 +5383,9 @@ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" }, "node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { "node": ">=6" } @@ -5418,15 +5398,20 @@ "color-parse": "^1.3.8" } }, + "node_modules/color-alpha/node_modules/color-parse": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.3.tgz", + "integrity": "sha512-BADfVl/FHkQkyo8sRBwMYBqemqsgnu7JZAwUgvBvuwwuNUZAhSvLTbsEErS5bQXzOjDR0dWzJ4vXN2Q+QoPx0A==", + "dependencies": { + "color-name": "^1.0.0" + } + }, "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "color-name": "1.1.3" } }, "node_modules/color-id": { @@ -5438,9 +5423,9 @@ } }, "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/color-normalize": { "version": "1.5.0", @@ -5453,13 +5438,11 @@ } }, "node_modules/color-parse": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.3.8.tgz", - "integrity": "sha512-1Y79qFv0n1xair3lNMTNeoFvmc3nirMVBij24zbs1f13+7fPpQClMg5b4AuKXLt3szj7BRlHMCXHplkce6XlmA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-2.0.0.tgz", + "integrity": "sha512-g2Z+QnWsdHLppAbrpcFWo629kLOnOPtpxYV69GCqm92gqSgyXbzlfyN3MXs0412fPBkFmiuS+rXposgBgBa6Kg==", "dependencies": { - "color-name": "^1.0.0", - "defined": "^1.0.0", - "is-plain-obj": "^1.1.0" + "color-name": "^1.0.0" } }, "node_modules/color-rgba": { @@ -5472,6 +5455,14 @@ "color-space": "^1.14.6" } }, + "node_modules/color-rgba/node_modules/color-parse": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.3.tgz", + "integrity": "sha512-BADfVl/FHkQkyo8sRBwMYBqemqsgnu7JZAwUgvBvuwwuNUZAhSvLTbsEErS5bQXzOjDR0dWzJ4vXN2Q+QoPx0A==", + "dependencies": { + "color-name": "^1.0.0" + } + }, "node_modules/color-space": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/color-space/-/color-space-1.16.0.tgz", @@ -5518,7 +5509,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/concat-stream": { "version": "1.6.2", @@ -5534,12 +5526,6 @@ "typedarray": "^0.0.6" } }, - "node_modules/confbox": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", - "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", - "dev": true - }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -5562,9 +5548,9 @@ } }, "node_modules/core-js": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.1.tgz", - "integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -5572,9 +5558,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.35.1.tgz", - "integrity": "sha512-zcIdi/CL3MWbBJYo5YCeVAAx+Sy9yJE9I3/u9LkFABwbeaPhTMRWraM8mYFp9jW5Z50hOy7FVzCc8dCrpZqtIQ==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz", + "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -5618,6 +5604,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5684,6 +5671,51 @@ "hyphenate-style-name": "^1.0.3" } }, + "node_modules/css-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/css-system-font-keywords": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-system-font-keywords/-/css-system-font-keywords-1.0.0.tgz", @@ -5719,36 +5751,44 @@ "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==" }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cssstyle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", - "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { "node": ">=18" } }, - "node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true - }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" } }, "node_modules/d3": { @@ -6057,46 +6097,63 @@ "node": ">=18" } }, - "node_modules/data-urls/node_modules/tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, "dependencies": { - "punycode": "^2.3.1" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/data-urls/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -6129,13 +6186,10 @@ } }, "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, "engines": { "node": ">=6" } @@ -6155,24 +6209,28 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", "engines": { "node": ">=0.10.0" } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -6223,23 +6281,14 @@ "integrity": "sha512-I3JIbrnKPAntNLl1I6TpSQQdQ4AutYzv/sKMFKbepawV/hlH0GmYKhUoOEMd4xqaUHT+Bm0f4127lh5qs1m1tw==" }, "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "optional": true, "engines": { "node": ">=8" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -6281,9 +6330,9 @@ } }, "node_modules/dompurify": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.7.tgz", - "integrity": "sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ==" + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.7.tgz", + "integrity": "sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==" }, "node_modules/draft-convert": { "version": "2.1.13", @@ -6365,10 +6414,16 @@ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/electron-to-chromium": { - "version": "1.4.805", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.805.tgz", - "integrity": "sha512-8W4UJwX/w9T0QSzINJckTKG6CYpAUTqsaWcWIsdud3I1FYJcMgW9QqT1/4CBff/pP/TihWh13OmiyY8neto6vw==" + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", + "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==" }, "node_modules/element-size": { "version": "1.1.1", @@ -6383,6 +6438,12 @@ "strongly-connected-components": "^1.0.1" } }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -6391,6 +6452,19 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -6420,50 +6494,57 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -6472,37 +6553,78 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-iterator-helpers": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", - "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "dev": true, "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.1", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", + "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.0.1" + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -6535,13 +6657,14 @@ } }, "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", "next-tick": "^1.1.0" }, "engines": { @@ -6559,12 +6682,15 @@ } }, "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" } }, "node_modules/es6-weak-map": { @@ -6579,9 +6705,9 @@ } }, "node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, "bin": { @@ -6591,35 +6717,35 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -6665,16 +6791,16 @@ } }, "node_modules/eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", - "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -6720,9 +6846,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", - "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -6732,20 +6858,21 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.0.tgz", - "integrity": "sha512-O2B1XLBJnUCRkggFzUQ+PBYJDit8iAgXdlu8ucolqGrbmOWPvttZQZX8d1sC0MbqDMSLs8SHSQxaNPRY1RQREg==", + "version": "48.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.10.0.tgz", + "integrity": "sha512-BEli0k8E0dzhJairAllwlkGnyYDZVKNn4WDmyKy+v6J5qGNuofjzxwNUi+55BOGmyO9mKBhqaidwGy+dxndn/Q==", "dev": true, "dependencies": { - "@es-joy/jsdoccomment": "~0.42.0", + "@es-joy/jsdoccomment": "~0.46.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.3.4", + "debug": "^4.3.5", "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.6.0", - "spdx-expression-parse": "^4.0.0" + "esquery": "^1.6.0", + "parse-imports": "^2.1.1", + "semver": "^7.6.3", + "spdx-expression-parse": "^4.0.0", + "synckit": "^0.9.1" }, "engines": { "node": ">=18" @@ -6754,24 +6881,46 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-license-header": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-license-header/-/eslint-plugin-license-header-0.6.1.tgz", + "integrity": "sha512-9aIz8q3OaMr1/uQmCGCWySjTs5nEXUJexNegz/8lluNcZbEl82Ag1Vyr1Hu3oIveRW1NbXDPs6nu4zu9mbrmWA==", + "dev": true, + "dependencies": { + "requireindex": "^1.2.0" + } + }, "node_modules/eslint-plugin-prettier": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", - "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.5" + "synckit": "^0.9.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/prettier" + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", + "eslint-config-prettier": "*", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -6784,39 +6933,41 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "version": "7.37.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.0.tgz", + "integrity": "sha512-IHBePmfWH5lKhJnJ7WB1V+v/GolbB0rjS8XYVCSQCZKaQCAUhMoVoOEn1Ef8Z8Wf0a7l8KTJvuZg5/e4qrZ6nA==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", + "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", + "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", "dev": true, "engines": { "node": ">=10" @@ -6826,14 +6977,24 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz", - "integrity": "sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==", + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.12.tgz", + "integrity": "sha512-9neVjoGv20FwYtCP6CB1dzR1vr57ZDNOXst21wd2xJ/cTlM2xLq0GWVlSNTdMn/4BtP6cHYBMCSp1wFBJ9jBsg==", "dev": true, "peerDependencies": { "eslint": ">=7" } }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -6846,58 +7007,182 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=8" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "*" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=0.10" } }, "node_modules/espree": { @@ -6930,9 +7215,9 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -6945,7 +7230,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -6978,6 +7262,15 @@ "node": ">=0.10.0" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -6986,41 +7279,6 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -7038,10 +7296,24 @@ "type": "^2.7.2" } }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/falafel": { "version": "2.2.5", @@ -7129,11 +7401,6 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fast-loops": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.3.tgz", - "integrity": "sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==" - }, "node_modules/fast-shallow-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", @@ -7145,9 +7412,9 @@ "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==" }, "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -7188,9 +7455,9 @@ } }, "node_modules/fbemitter/node_modules/ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.39.tgz", + "integrity": "sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==", "funding": [ { "type": "opencollective", @@ -7205,6 +7472,9 @@ "url": "https://github.com/sponsors/faisalman" } ], + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { "node": "*" } @@ -7259,9 +7529,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -7289,14 +7560,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-yarn-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "dependencies": { - "micromatch": "^4.0.2" - } - }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -7312,9 +7575,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/flatten-vertex-data": { @@ -7352,9 +7615,9 @@ } }, "node_modules/flux/node_modules/ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.39.tgz", + "integrity": "sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==", "funding": [ { "type": "opencollective", @@ -7369,14 +7632,17 @@ "url": "https://github.com/sponsors/faisalman" } ], + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { "node": "*" } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -7417,6 +7683,22 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -7453,24 +7735,11 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "optional": true }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -7549,15 +7818,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7574,13 +7848,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -7589,6 +7864,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -7606,9 +7889,9 @@ "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==" }, "node_modules/gl-text": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/gl-text/-/gl-text-1.3.1.tgz", - "integrity": "sha512-/f5gcEMiZd+UTBJLTl3D+CkCB/0UFGTx3nflH8ZmyWcLkZhsZ1+Xx5YYkw2rgWAzgPeE35xCqBuHSoMKQVsR+w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gl-text/-/gl-text-1.4.0.tgz", + "integrity": "sha512-o47+XBqLCj1efmuNyCHt7/UEJmB9l66ql7pnobD6p+sgmBUdzfMZXIF0zD2+KRfpd99DJN+QXdvTFAGCKCVSmQ==", "dependencies": { "bit-twiddle": "^1.0.2", "color-normalize": "^1.5.0", @@ -7647,6 +7930,8 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7674,28 +7959,85 @@ "node": ">=10.13.0" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "peer": true + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" + } + }, + "node_modules/global-prefix": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-4.0.0.tgz", + "integrity": "sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==", + "dependencies": { + "ini": "^4.1.3", + "kind-of": "^6.0.3", + "which": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=16" + } + }, + "node_modules/global-prefix/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -7917,6 +8259,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -7941,20 +8284,20 @@ "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==" }, "node_modules/handsontable": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/handsontable/-/handsontable-14.1.0.tgz", - "integrity": "sha512-7j6rvOTyNoz84u6ZjCluGhQp+VCVGi0bg2Os5cCTaStyDjyB5y/b0En8qWMyXMTcXzN+GeDn8eB+N6dqSYPnTg==", + "version": "14.5.0", + "resolved": "https://registry.npmjs.org/handsontable/-/handsontable-14.5.0.tgz", + "integrity": "sha512-fxCjDZS4z2LFwrmHXqtEKIcfrPxoD8+5AmX7r3pEYp2rjIhmtYKA45DFQ/3PP8PYvSFW8BGR58ZaKecMpGfJXg==", "dependencies": { "@handsontable/pikaday": "^1.0.0", "@types/pikaday": "1.7.4", - "core-js": "^3.31.1", + "core-js": "^3.37.0", "dompurify": "^2.1.1", - "moment": "2.29.4", + "moment": "2.30.1", "numbro": "2.1.2", "pikaday": "1.8.2" }, "optionalDependencies": { - "hyperformula": "^2.4.0" + "hyperformula": "^2.6.2" } }, "node_modules/has-bigints": { @@ -7967,11 +8310,11 @@ } }, "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/has-hover": { @@ -7991,20 +8334,22 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -8016,6 +8361,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -8024,12 +8370,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -8039,9 +8385,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -8162,9 +8508,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, "dependencies": { "agent-base": "^7.0.2", @@ -8174,50 +8520,40 @@ "node": ">= 14" } }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" } }, "node_modules/hyperformula": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/hyperformula/-/hyperformula-2.6.1.tgz", - "integrity": "sha512-GzL+R+UweB4FtT7p71cDS0wFVq5CMUjBincSSVzccBsPRgw4aIc/GbWLuuvrX6mH/r2ubYDu6udnr1/+OMoI9w==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hyperformula/-/hyperformula-2.7.1.tgz", + "integrity": "sha512-mpVF5zOyNpksZzgTaCQyRAzdC/X43+taz5x1n7zNbs/PUUv0AuLmsy2yfihCr+vihUzN/pk+gXBbOfNpXKOpgA==", "optional": true, "dependencies": { "chevrotain": "^6.5.0", - "tiny-emitter": "^2.1.0", - "unorm": "^1.6.0" + "tiny-emitter": "^2.1.0" } }, "node_modules/hyphenate-style-name": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", - "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==" }, "node_modules/i18next": { - "version": "23.5.1", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.5.1.tgz", - "integrity": "sha512-JelYzcaCoFDaa+Ysbfz2JsGAKkrHiMG6S61+HLBUEIPaF40WMwW9hCPymlQGrP+wWawKxKPuSuD71WZscCsWHg==", + "version": "23.15.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.15.1.tgz", + "integrity": "sha512-wB4abZ3uK7EWodYisHl/asf8UYEhrI/vj/8aoSsrj/ZDxj4/UXPOa1KvFt1Fq5hkUHquNqwFlDprmjZ8iySgYA==", "funding": [ { "type": "individual", @@ -8233,21 +8569,21 @@ } ], "dependencies": { - "@babel/runtime": "^7.22.5" + "@babel/runtime": "^7.23.2" } }, "node_modules/i18next-browser-languagedetector": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.1.0.tgz", - "integrity": "sha512-cr2k7u1XJJ4HTOjM9GyOMtbOA47RtUoWRAtt52z43r3AoMs2StYKyjS3URPhzHaf+mn10hY9dZWamga5WPQjhA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz", + "integrity": "sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==", "dependencies": { - "@babel/runtime": "^7.19.4" + "@babel/runtime": "^7.23.2" } }, "node_modules/i18next-http-backend": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.4.2.tgz", - "integrity": "sha512-wKrgGcaFQ4EPjfzBTjzMU0rbFTYpa0S5gv9N/d8WBmWS64+IgJb7cHddMvV+tUkse7vUfco3eVs2lB+nJhPo3w==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.6.1.tgz", + "integrity": "sha512-rCilMAnlEQNeKOZY1+x8wLM5IpYOj10guGvEpeC59tNjj6MMreLIjIW8D1RclhD3ifLwn6d/Y9HEM1RUE6DSog==", "dependencies": { "cross-fetch": "4.0.0" } @@ -8271,6 +8607,17 @@ "node": ">=0.10.0" } }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -8291,18 +8638,18 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/immer": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.3.tgz", - "integrity": "sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -8353,6 +8700,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -8361,30 +8710,31 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "optional": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/inline-style-prefixer": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.0.tgz", - "integrity": "sha512-I7GEdScunP1dQ6IM2mQWh6v0mOYdYmH3Bp31UecKdrcUgcURTcctSe1IECdUznSHKSmsHtjrT3CwCPI1pyxfUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", "dependencies": { - "css-in-js-utils": "^3.1.0", - "fast-loops": "^1.1.3" + "css-in-js-utils": "^3.1.0" } }, "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -8423,14 +8773,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8489,21 +8841,6 @@ "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==" }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -8517,11 +8854,29 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8551,20 +8906,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", @@ -8576,17 +8917,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-extendable/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -8627,6 +8957,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -8672,10 +9011,13 @@ } }, "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8686,9 +9028,9 @@ "integrity": "sha512-mlcHZA84t1qLSuWkt2v0I2l61PYdyQDt4aG1mLIXF5FDMm4+haBCxCPYSr/uwqQNRk1MiTizn0ypEuRAOLRAew==" }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -8701,6 +9043,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "engines": { "node": ">=0.12.0" } @@ -8746,9 +9089,12 @@ } }, "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, "engines": { "node": ">=0.10.0" } @@ -8776,36 +9122,30 @@ } }, "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-string": { @@ -8849,12 +9189,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -8864,10 +9204,13 @@ } }, "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8885,29 +9228,21 @@ } }, "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -8916,7 +9251,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/isobject": { "version": "3.0.1", @@ -8949,10 +9285,31 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-source-maps": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", - "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.23", @@ -8989,11 +9346,64 @@ "set-function-name": "^2.0.1" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/javascript-natural-sort": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/jmespath": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", @@ -9041,31 +9451,31 @@ } }, "node_modules/jsdom": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", - "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, "dependencies": { - "cssstyle": "^4.0.1", + "cssstyle": "^4.1.0", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.10", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.4", + "tough-cookie": "^5.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.17.0", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -9080,40 +9490,6 @@ } } }, - "node_modules/jsdom/node_modules/tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/jsdom/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdom/node_modules/whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, - "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -9146,29 +9522,17 @@ "resolved": "https://registry.npmjs.org/json-source-map/-/json-source-map-0.6.1.tgz", "integrity": "sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg==" }, - "node_modules/json-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz", - "integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==", - "dependencies": { - "call-bind": "^1.0.5", - "isarray": "^2.0.5", - "jsonify": "^0.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stringify-pretty-compact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9181,44 +9545,25 @@ } }, "node_modules/jsoneditor": { - "version": "9.10.4", - "resolved": "https://registry.npmjs.org/jsoneditor/-/jsoneditor-9.10.4.tgz", - "integrity": "sha512-tr7dSARLHM65OQTE81zo5fQAjLzijLl+u/z+pcJaeaFzgkey59Gi8TDCYIejQ/plvm6RLVmuEeqgDhsQdayhiQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/jsoneditor/-/jsoneditor-10.1.0.tgz", + "integrity": "sha512-s+BP/x9Rx9ukNyTjeWCvIAGTEvXwCw6l4NX4mlxXfkK87F1ZgsesHbD9SsyZDLP27dvcFgr9H/j1jy/Bzzk07Q==", "dependencies": { - "ace-builds": "^1.31.1", + "ace-builds": "^1.35.0", "ajv": "^6.12.6", "javascript-natural-sort": "^0.7.1", "jmespath": "^0.16.0", "json-source-map": "^0.6.1", - "jsonrepair": "^3.4.0", + "jsonrepair": "^3.8.0", "mobius1-selectr": "^2.4.13", "picomodal": "^3.0.0", - "vanilla-picker": "^2.12.2" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "vanilla-picker": "^2.12.3" } }, "node_modules/jsonrepair": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.5.1.tgz", - "integrity": "sha512-F0VxiEj1j7m1OAVUVy6fFYk5s8tthF61J7tjYtEACw1DeNQqKmZF6dPddduxc7Tc5IrLqKTdLAwUNTmrqqg+hw==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.8.1.tgz", + "integrity": "sha512-5wnjaO53EJOhfLFY92nvBz2B9gqF9ql/D4HKUb1WOSBaqtVcAifFfmurblnhCJn/ySqKFA8U3n7nhGMAu/hEjQ==", "bin": { "jsonrepair": "bin/cli.js" } @@ -9239,14 +9584,17 @@ } }, "node_modules/jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } }, "node_modules/kdbush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", - "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" }, "node_modules/keyv": { "version": "4.5.4", @@ -9257,12 +9605,12 @@ "json-buffer": "3.0.1" } }, - "node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "dependencies": { - "graceful-fs": "^4.1.11" + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" } }, "node_modules/levn": { @@ -9282,21 +9630,14 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/local-pkg": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", - "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", - "dev": true, - "dependencies": { - "mlly": "^1.4.2", - "pkg-types": "^1.0.3" - }, + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "peer": true, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "node": ">=6.11.5" } }, "node_modules/locate-path": { @@ -9355,9 +9696,9 @@ } }, "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", "dev": true, "dependencies": { "get-func-name": "^2.0.1" @@ -9377,14 +9718,11 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "yallist": "^3.0.2" } }, "node_modules/lz-string": { @@ -9398,22 +9736,22 @@ } }, "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, @@ -9432,6 +9770,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/map-limit": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz", @@ -9449,11 +9799,12 @@ } }, "node_modules/mapbox-gl": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.10.1.tgz", - "integrity": "sha512-0aHt+lFUpYfvh0kMIqXqNXqoYMuhuAsMlw87TbhWrw78Tx2zfuPI0Lx31/YPUgJ+Ire0tzQ4JnuBL7acDNXmMg==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.13.3.tgz", + "integrity": "sha512-p8lJFEiqmEQlyv+DQxFAOG/XPWN0Wp7j/Psq93Zywz7qt9CcUKFYDBOoOEKzqe6gudHVJY8/Bhqw6VDpX2lSBg==", + "peer": true, "dependencies": { - "@mapbox/geojson-rewind": "^0.5.0", + "@mapbox/geojson-rewind": "^0.5.2", "@mapbox/geojson-types": "^1.0.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^1.5.0", @@ -9467,13 +9818,12 @@ "geojson-vt": "^3.2.1", "gl-matrix": "^3.2.1", "grid-index": "^1.1.0", - "minimist": "^1.2.5", "murmurhash-js": "^1.0.0", "pbf": "^3.2.1", "potpack": "^1.0.1", "quickselect": "^2.0.0", "rw": "^1.3.3", - "supercluster": "^7.0.0", + "supercluster": "^7.1.0", "tinyqueue": "^2.0.3", "vt-pbf": "^3.1.1" }, @@ -9481,6 +9831,89 @@ "node": ">=6.4.0" } }, + "node_modules/maplibre-gl": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.7.1.tgz", + "integrity": "sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA==", + "dependencies": { + "@mapbox/geojson-rewind": "^0.5.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^2.0.6", + "@mapbox/unitbezier": "^0.0.1", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "@maplibre/maplibre-gl-style-spec": "^20.3.1", + "@types/geojson": "^7946.0.14", + "@types/geojson-vt": "3.2.5", + "@types/mapbox__point-geometry": "^0.1.4", + "@types/mapbox__vector-tile": "^1.3.4", + "@types/pbf": "^3.0.5", + "@types/supercluster": "^7.1.3", + "earcut": "^3.0.0", + "geojson-vt": "^4.0.2", + "gl-matrix": "^3.4.3", + "global-prefix": "^4.0.0", + "kdbush": "^4.0.2", + "murmurhash-js": "^1.0.0", + "pbf": "^3.3.0", + "potpack": "^2.0.0", + "quickselect": "^3.0.0", + "supercluster": "^8.0.1", + "tinyqueue": "^3.0.0", + "vt-pbf": "^3.1.3" + }, + "engines": { + "node": ">=16.14.0", + "npm": ">=8.1.0" + }, + "funding": { + "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" + } + }, + "node_modules/maplibre-gl/node_modules/@mapbox/tiny-sdf": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz", + "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==" + }, + "node_modules/maplibre-gl/node_modules/@mapbox/unitbezier": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==" + }, + "node_modules/maplibre-gl/node_modules/earcut": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.0.tgz", + "integrity": "sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==" + }, + "node_modules/maplibre-gl/node_modules/geojson-vt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz", + "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==" + }, + "node_modules/maplibre-gl/node_modules/potpack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz", + "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==" + }, + "node_modules/maplibre-gl/node_modules/quickselect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==" + }, + "node_modules/maplibre-gl/node_modules/supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "dependencies": { + "kdbush": "^4.0.2" + } + }, + "node_modules/maplibre-gl/node_modules/tinyqueue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==" + }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", @@ -9499,13 +9932,13 @@ "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" }, "node_modules/material-react-table": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/material-react-table/-/material-react-table-2.0.5.tgz", - "integrity": "sha512-axRrqa/2QQ+AO3SiJbOtSyemlHX0S03X+IXW72z344d3LT+u/jsKiAmdWMLTN8ARScYMAN5NgrArujiLEmftSQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/material-react-table/-/material-react-table-3.0.1.tgz", + "integrity": "sha512-RP+bnpsOAH5j6zwP04u9HB37fyqbd6mVv9mkT4IUJC3e3gEqixZmkNdJMVM1ZVHoq7yIaM381xf22mpBVe0IaA==", "dependencies": { - "@tanstack/match-sorter-utils": "8.8.4", - "@tanstack/react-table": "8.10.7", - "@tanstack/react-virtual": "3.0.1", + "@tanstack/match-sorter-utils": "8.19.4", + "@tanstack/react-table": "8.20.5", + "@tanstack/react-virtual": "3.10.6", "highlight-words": "1.2.2" }, "engines": { @@ -9516,11 +9949,11 @@ "url": "https://github.com/sponsors/kevinvandy" }, "peerDependencies": { - "@emotion/react": ">=11.11", - "@emotion/styled": ">=11.11", - "@mui/icons-material": ">=5.11", - "@mui/material": ">=5.13", - "@mui/x-date-pickers": ">=6.15.0", + "@emotion/react": ">=11.13", + "@emotion/styled": ">=11.13", + "@mui/icons-material": ">=6", + "@mui/material": ">=6", + "@mui/x-date-pickers": ">=7.15", "react": ">=18.0", "react-dom": ">=18.0" } @@ -9547,7 +9980,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "peer": true }, "node_modules/merge2": { "version": "1.4.1", @@ -9559,11 +9992,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -9589,18 +10023,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -9634,14 +10056,17 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -9652,33 +10077,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "optional": true }, - "node_modules/mlly": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", - "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.1.1", - "ufo": "^1.5.3" - } - }, "node_modules/mobius1-selectr": { "version": "2.4.13", "resolved": "https://registry.npmjs.org/mobius1-selectr/-/mobius1-selectr-2.4.13.tgz", "integrity": "sha512-Mk9qDrvU44UUL0EBhbAA1phfQZ7aMZPjwtL7wkpiBzGh8dETGqfsh50mWoX9EkjDlkONlErWXArHCKfoxVg0Bw==" }, "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "engines": { "node": "*" } @@ -9721,9 +10143,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mumath": { "version": "3.3.4", @@ -9740,21 +10162,21 @@ "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==" }, "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", "optional": true }, "node_modules/nano-css": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.1.tgz", - "integrity": "sha512-T2Mhc//CepkTa3X4pUhKgbEheJHYAxD0VptuqFhDbGMUWVV2m+lkNiW/Ieuj35wrfC8Zm0l7HvssQh7zcEttSw==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", + "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", "css-tree": "^1.1.2", "csstype": "^3.1.2", "fastest-stable-stringify": "^2.0.2", - "inline-style-prefixer": "^7.0.0", + "inline-style-prefixer": "^7.0.1", "rtl-css-js": "^1.16.1", "stacktrace-js": "^2.0.2", "stylis": "^4.3.0" @@ -9765,15 +10187,14 @@ } }, "node_modules/nano-css/node_modules/stylis": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", - "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", + "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==" }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -9828,15 +10249,29 @@ "ms": "^2.1.1" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "peer": true + }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "engines": { + "node": ">= 10" + } + }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, "node_modules/node-abi": { - "version": "3.54.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", - "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==", + "version": "3.68.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.68.0.tgz", + "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==", "optional": true, "dependencies": { "semver": "^7.3.5" @@ -9845,6 +10280,18 @@ "node": ">=10" } }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", @@ -9903,10 +10350,29 @@ "url": "https://opencollective.com/node-fetch" } }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-svg-path": { "version": "0.1.0", @@ -9942,33 +10408,6 @@ "node": ">=6" } }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/number-is-integer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-integer/-/number-is-integer-1.0.1.tgz", @@ -9992,9 +10431,9 @@ } }, "node_modules/nwsapi": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", - "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==", + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", "dev": true }, "node_modules/object-assign": { @@ -10006,9 +10445,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10017,6 +10460,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -10040,28 +10484,29 @@ } }, "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -10070,19 +10515,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.omit": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-3.0.0.tgz", @@ -10095,14 +10527,14 @@ } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -10119,61 +10551,45 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, + "node_modules/openapi-path-templating": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/openapi-path-templating/-/openapi-path-templating-1.6.0.tgz", + "integrity": "sha512-1atBNwOUrZXthTvlvvX8k8ovFEF3iA8mDidYMkdOtvVdndBhTrspbwGXNOzEUaJhm9iUl4Tf5uQaeTLAJvwPig==", "dependencies": { - "mimic-fn": "^4.0.0" + "apg-lite": "^1.0.3" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12.20.0" } }, - "node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "node_modules/openapi-server-url-templating": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/openapi-server-url-templating/-/openapi-server-url-templating-1.1.0.tgz", + "integrity": "sha512-dtyTFKx2xVcO0W8JKaluXIHC9l/MLjHeflBaWjiWNMCHp/TBs9dEjQDbj/VFlHR4omFOKjjmqm1pW1aCAhmPBg==", "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" + "apg-lite": "^1.0.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12.20.0" } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -10202,6 +10618,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10235,6 +10657,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/parse-imports": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", + "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "dev": true, + "dependencies": { + "es-module-lexer": "^1.5.3", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -10282,62 +10717,6 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/patch-package": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", - "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", - "dependencies": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^4.1.2", - "ci-info": "^3.7.0", - "cross-spawn": "^7.0.3", - "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^9.0.0", - "json-stable-stringify": "^1.0.2", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.6", - "open": "^7.4.2", - "rimraf": "^2.6.3", - "semver": "^7.5.3", - "slash": "^2.0.0", - "tmp": "^0.0.33", - "yaml": "^2.2.2" - }, - "bin": { - "patch-package": "index.js" - }, - "engines": { - "node": ">=14", - "npm": ">5" - } - }, - "node_modules/patch-package/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/patch-package/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/patch-package/node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "engines": { - "node": ">= 14" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -10350,6 +10729,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10358,6 +10738,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -10367,6 +10748,28 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -10382,18 +10785,18 @@ "dev": true }, "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, "engines": { - "node": "*" + "node": ">= 14.16" } }, "node_modules/pbf": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", - "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz", + "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", "dependencies": { "ieee754": "^1.1.12", "resolve-protobuf-schema": "^2.1.0" @@ -10413,14 +10816,15 @@ "integrity": "sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw==" }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -10435,37 +10839,29 @@ }, "node_modules/pikaday": { "version": "1.8.2", - "resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.2.tgz", - "integrity": "sha512-TNtsE+34BIax3WtkB/qqu5uepV1McKYEgvL3kWzU7aqPCpMEN6rBF3AOwu4WCwAealWlBGobXny/9kJb49C1ew==" - }, - "node_modules/pkg-types": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz", - "integrity": "sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==", - "dev": true, - "dependencies": { - "confbox": "^0.1.7", - "mlly": "^1.7.0", - "pathe": "^1.1.2" - } + "resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.2.tgz", + "integrity": "sha512-TNtsE+34BIax3WtkB/qqu5uepV1McKYEgvL3kWzU7aqPCpMEN6rBF3AOwu4WCwAealWlBGobXny/9kJb49C1ew==" }, "node_modules/plotly.js": { - "version": "2.26.1", - "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-2.26.1.tgz", - "integrity": "sha512-aZgY5NEbuwgsnbTNmMy3BXPkx/QK+wuSnnEWvEeeUnhEZK+fTKazx6zCsbImLPinOvQtTdOXH4LhqrTYcYd69g==", + "version": "2.35.2", + "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-2.35.2.tgz", + "integrity": "sha512-s0knlWzRvLQXxzf3JQ6qbm8FpwKuMjkr+6r04f8/yCEByAQ+I0jkUzY/hSGRGb+u7iljTh9hgpEiiJP90vjyeQ==", "dependencies": { - "@plotly/d3": "3.8.1", + "@plotly/d3": "3.8.2", "@plotly/d3-sankey": "0.7.2", "@plotly/d3-sankey-circular": "0.33.1", - "@turf/area": "^6.4.0", - "@turf/bbox": "^6.4.0", - "@turf/centroid": "^6.0.2", + "@plotly/mapbox-gl": "1.13.4", + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/centroid": "^7.1.0", + "base64-arraybuffer": "^1.0.2", "canvas-fit": "^1.5.0", "color-alpha": "1.0.4", "color-normalize": "1.5.0", - "color-parse": "1.3.8", + "color-parse": "2.0.0", "color-rgba": "2.1.1", "country-regex": "^1.1.0", + "css-loader": "^7.1.2", "d3-force": "^1.2.1", "d3-format": "^1.4.5", "d3-geo": "^1.12.1", @@ -10476,26 +10872,26 @@ "d3-time-format": "^2.2.3", "fast-isnumeric": "^1.1.4", "gl-mat4": "^1.2.0", - "gl-text": "^1.3.1", - "glslify": "^7.1.1", + "gl-text": "^1.4.0", "has-hover": "^1.0.1", "has-passive-events": "^1.0.0", "is-mobile": "^4.0.0", - "mapbox-gl": "1.10.1", + "maplibre-gl": "^4.5.2", "mouse-change": "^1.4.0", "mouse-event-offset": "^3.0.2", "mouse-wheel": "^1.2.0", "native-promise-only": "^0.8.1", "parse-svg-path": "^0.1.2", "point-in-polygon": "^1.1.0", - "polybooljs": "^1.2.0", + "polybooljs": "^1.2.2", "probe-image-size": "^7.2.3", "regl": "npm:@plotly/regl@^2.1.2", "regl-error2d": "^2.0.12", - "regl-line2d": "^3.1.2", - "regl-scatter2d": "^3.2.9", + "regl-line2d": "^3.1.3", + "regl-scatter2d": "^3.3.1", "regl-splom": "^1.0.14", "strongly-connected-components": "^1.0.1", + "style-loader": "^4.0.0", "superscript-text": "^1.0.0", "svg-path-sdf": "^1.1.3", "tinycolor2": "^1.4.2", @@ -10522,15 +10918,23 @@ "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==" }, "node_modules/polybooljs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/polybooljs/-/polybooljs-1.2.0.tgz", - "integrity": "sha512-mKjR5nolISvF+q2BtC1fi/llpxBPTQ3wLWN8+ldzdw2Hocpc8C72ZqnamCM4Z6z+68GVVjkeM01WJegQmZ8MEQ==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/polybooljs/-/polybooljs-1.2.2.tgz", + "integrity": "sha512-ziHW/02J0XuNuUtmidBc6GXE8YohYydp3DWPWXYsd7O721TjcmN+k6ezjdwkDqep+gnWnFY+yqZHvzElra2oCg==" }, - "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "funding": [ { "type": "opencollective", @@ -10547,22 +10951,94 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, "node_modules/potpack": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" }, "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "optional": true, "dependencies": { "detect-libc": "^2.0.0", @@ -10595,9 +11071,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -10622,17 +11098,18 @@ } }, "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, + "peer": true, "dependencies": { - "@jest/schemas": "^29.6.3", + "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "react-is": "^17.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/pretty-format/node_modules/ansi-styles": { @@ -10640,6 +11117,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "peer": true, "engines": { "node": ">=10" }, @@ -10647,6 +11125,13 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "peer": true + }, "node_modules/prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -10723,16 +11208,10 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "optional": true, "dependencies": { "end-of-stream": "^1.1.0", @@ -10752,20 +11231,6 @@ "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==" }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -10810,18 +11275,18 @@ "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" }, "node_modules/ramda": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", - "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.30.1.tgz", + "integrity": "sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/ramda" } }, "node_modules/ramda-adjunct": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ramda-adjunct/-/ramda-adjunct-4.1.1.tgz", - "integrity": "sha512-BnCGsZybQZMDGram9y7RiryoRHS5uwx8YeGuUeDKuZuvK38XO6JJfmK85BwRWAKFA6pZ5nZBO/HBFtExVaf31w==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ramda-adjunct/-/ramda-adjunct-5.1.0.tgz", + "integrity": "sha512-8qCpl2vZBXEJyNbi4zqcgdfHtcdsWjOGbiNSEnEBrM6Y0OKOT8UxJbIVGm1TIcjaSu2MxaWcgtsNlKlCk7o7qg==", "engines": { "node": ">=0.10.3" }, @@ -10830,7 +11295,7 @@ "url": "https://opencollective.com/ramda-adjunct" }, "peerDependencies": { - "ramda": ">= 0.29.0" + "ramda": ">= 0.30.0" } }, "node_modules/randexp": { @@ -10868,6 +11333,12 @@ "rc": "cli.js" } }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "optional": true + }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -10878,9 +11349,9 @@ } }, "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dependencies": { "loose-envify": "^1.1.0" }, @@ -11000,15 +11471,15 @@ } }, "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "^18.2.0" + "react": "^18.3.1" } }, "node_modules/react-dropzone": { @@ -11040,18 +11511,18 @@ } }, "node_modules/react-hook-form": { - "version": "7.47.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.47.0.tgz", - "integrity": "sha512-F/TroLjTICipmHeFlMrLtNLceO2xr1jU3CyiNla5zdwsGUGu2UOxxR4UyJgLlhMwLW/Wzp4cpJ7CPfgJIeKdSg==", + "version": "7.53.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", + "integrity": "sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==", "engines": { - "node": ">=12.22.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/react-hook-form" }, "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18" + "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "node_modules/react-html-attributes": { @@ -11063,11 +11534,11 @@ } }, "node_modules/react-i18next": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.2.2.tgz", - "integrity": "sha512-+nFUkbRByFwnrfDcYqvzBuaeZb+nACHx+fAWN/pZMddWOCJH5hoc21+Sa/N/Lqi6ne6/9wC/qRGOoQhJa6IkEQ==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.0.2.tgz", + "integrity": "sha512-z0W3/RES9Idv3MmJUcf0mDNeeMOUXe+xoL0kPfQPbDoZHmni/XsIoq5zgT2MCFUiau283GuBUK578uD/mkAbLQ==", "dependencies": { - "@babel/runtime": "^7.22.5", + "@babel/runtime": "^7.25.0", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { @@ -11113,9 +11584,9 @@ } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/react-json-view": { "version": "1.21.3", @@ -11138,12 +11609,9 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, "node_modules/react-number-format": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.0.tgz", - "integrity": "sha512-NWdICrqLhI7rAS8yUeLVd6Wr4cN7UjJ9IBTS0f/a9i7UB4x4Ti70kGnksBtZ7o4Z7YRbvCMMR/jQmkoOBa/4fg==", - "dependencies": { - "prop-types": "^15.7.2" - }, + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.2.tgz", + "integrity": "sha512-cg//jVdS49PYDgmcYoBnMMHl4XNTMuV723ZnHD2aXYtWWWqbVF3hjQ8iB+UZEuXapLbeA8P8H+1o6ZB1lcw3vg==", "peerDependencies": { "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" @@ -11302,9 +11770,9 @@ } }, "node_modules/react-use": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.4.0.tgz", - "integrity": "sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==", + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.5.1.tgz", + "integrity": "sha512-LG/uPEVRflLWMwi3j/sZqR00nF6JGqTTDblkXK2nzXsIvij06hXl1V/MZIlwj1OKIQUtlh1l9jK8gLsRyCQxMg==", "dependencies": { "@types/js-cookie": "^2.2.6", "@xobotyi/scrollbar-width": "^1.9.5", @@ -11312,7 +11780,7 @@ "fast-deep-equal": "^3.1.3", "fast-shallow-equal": "^1.0.0", "js-cookie": "^2.2.1", - "nano-css": "^5.3.1", + "nano-css": "^5.6.2", "react-universal-interface": "^0.6.2", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.1.0", @@ -11322,8 +11790,8 @@ "tslib": "^2.1.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "*", + "react-dom": "*" } }, "node_modules/react-use/node_modules/@types/js-cookie": { @@ -11337,18 +11805,18 @@ "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" }, "node_modules/react-virtualized-auto-sizer": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.20.tgz", - "integrity": "sha512-OdIyHwj4S4wyhbKHOKM1wLSj/UDXm839Z3Cvfg2a9j+He6yDa6i5p0qQvEiCnyQlGO/HyfSnigQwuxvYalaAXA==", + "version": "1.0.24", + "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.24.tgz", + "integrity": "sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==", "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc", - "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc" + "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", + "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" } }, "node_modules/react-window": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.9.tgz", - "integrity": "sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q==", + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.10.tgz", + "integrity": "sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==", "dependencies": { "@babel/runtime": "^7.0.0", "memoize-one": ">=3.1.1 <6" @@ -11423,15 +11891,16 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" }, @@ -11476,14 +11945,15 @@ "optional": true }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -11513,9 +11983,9 @@ } }, "node_modules/regl-line2d": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/regl-line2d/-/regl-line2d-3.1.2.tgz", - "integrity": "sha512-nmT7WWS/WxmXAQMkgaMKWXaVmwJ65KCrjbqHGOUjjqQi6shfT96YbBOvelXwO9hG7/hjvbzjtQ2UO0L3e7YaXQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/regl-line2d/-/regl-line2d-3.1.3.tgz", + "integrity": "sha512-fkgzW+tTn4QUQLpFKsUIE0sgWdCmXAM3ctXcCgoGBZTSX5FE2A0M7aynz7nrZT5baaftLrk9te54B+MEq4QcSA==", "dependencies": { "array-bounds": "^1.0.1", "array-find-index": "^1.0.2", @@ -11524,7 +11994,6 @@ "earcut": "^2.1.5", "es6-weak-map": "^2.0.3", "flatten-vertex-data": "^1.0.2", - "glslify": "^7.0.0", "object-assign": "^4.1.1", "parse-rect": "^1.2.0", "pick-by-alias": "^1.2.0", @@ -11592,9 +12061,9 @@ } }, "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" }, "node_modules/repeat-string": { "version": "1.6.1", @@ -11604,6 +12073,15 @@ "node": ">=0.10" } }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -11678,6 +12156,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -11690,12 +12169,12 @@ } }, "node_modules/rollup": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", - "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz", + "integrity": "sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==", "dev": true, "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -11705,19 +12184,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.9.6", - "@rollup/rollup-android-arm64": "4.9.6", - "@rollup/rollup-darwin-arm64": "4.9.6", - "@rollup/rollup-darwin-x64": "4.9.6", - "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", - "@rollup/rollup-linux-arm64-gnu": "4.9.6", - "@rollup/rollup-linux-arm64-musl": "4.9.6", - "@rollup/rollup-linux-riscv64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-musl": "4.9.6", - "@rollup/rollup-win32-arm64-msvc": "4.9.6", - "@rollup/rollup-win32-ia32-msvc": "4.9.6", - "@rollup/rollup-win32-x64-msvc": "4.9.6", + "@rollup/rollup-android-arm-eabi": "4.22.5", + "@rollup/rollup-android-arm64": "4.22.5", + "@rollup/rollup-darwin-arm64": "4.22.5", + "@rollup/rollup-darwin-x64": "4.22.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.5", + "@rollup/rollup-linux-arm-musleabihf": "4.22.5", + "@rollup/rollup-linux-arm64-gnu": "4.22.5", + "@rollup/rollup-linux-arm64-musl": "4.22.5", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.5", + "@rollup/rollup-linux-riscv64-gnu": "4.22.5", + "@rollup/rollup-linux-s390x-gnu": "4.22.5", + "@rollup/rollup-linux-x64-gnu": "4.22.5", + "@rollup/rollup-linux-x64-musl": "4.22.5", + "@rollup/rollup-win32-arm64-msvc": "4.22.5", + "@rollup/rollup-win32-ia32-msvc": "4.22.5", + "@rollup/rollup-win32-x64-msvc": "4.22.5", "fsevents": "~2.3.2" } }, @@ -11764,13 +12246,13 @@ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -11801,13 +12283,13 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", - "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, "engines": { @@ -11823,9 +12305,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" }, "node_modules/saxes": { "version": "6.0.0", @@ -11840,13 +12322,31 @@ } }, "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "dependencies": { "loose-envify": "^1.1.0" } }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/screenfull": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", @@ -11859,17 +12359,11 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/serialize-error": { @@ -11886,30 +12380,42 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11923,6 +12429,28 @@ "node": ">=6.9" } }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -11949,6 +12477,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -11960,27 +12489,33 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } }, "node_modules/short-unique-id": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.0.3.tgz", - "integrity": "sha512-yhniEILouC0s4lpH0h7rJsfylZdca10W9mDJRAFh3EpcSUanCHGb0R7kcFOIUCZYSAPo0PUD5ZxWQdW0T4xaug==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.2.0.tgz", + "integrity": "sha512-cMGfwNyfDZ/nzJ2k2M+ClthBIh//GlZl1JEf47Uoa9XR11bz8Pa2T2wQO4bVrRdH48LrIDWJahQziKo3MjhsWg==", "bin": { "short-unique-id": "bin/short-unique-id", "suid": "bin/short-unique-id" } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12077,6 +12612,52 @@ "node": ">=8" } }, + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true + }, + "node_modules/sort-asc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", + "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-desc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz", + "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-object": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz", + "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", + "dependencies": { + "bytewise": "^1.1.0", + "get-value": "^2.0.2", + "is-extendable": "^0.1.1", + "sort-asc": "^0.2.0", + "sort-desc": "^0.2.0", + "union-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-object/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -12086,10 +12667,28 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -12120,11 +12719,34 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", - "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", "dev": true }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/split.js": { "version": "1.6.5", "resolved": "https://registry.npmjs.org/split.js/-/split.js-1.6.5.tgz", @@ -12189,11 +12811,6 @@ "stacktrace-gps": "^3.0.4" } }, - "node_modules/stampit": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/stampit/-/stampit-4.3.2.tgz", - "integrity": "sha512-pE2org1+ZWQBnIxRPrBM2gVupkuDD0TTNIo1H6GdT/vO82NXli2z8lRE8cu/nBIHrcOCXFBAHpb9ZldrB2/qOA==" - }, "node_modules/static-eval": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz", @@ -12234,56 +12851,138 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-split-by": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string-split-by/-/string-split-by-1.0.0.tgz", + "integrity": "sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==", + "dependencies": { + "parenthesis": "^3.1.5" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, - "node_modules/string-split-by": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string-split-by/-/string-split-by-1.0.0.tgz", - "integrity": "sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "dependencies": { - "parenthesis": "^3.1.5" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -12293,28 +12992,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12332,16 +13034,17 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, "node_modules/strip-indent": { @@ -12368,29 +13071,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", - "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", - "dev": true, - "dependencies": { - "js-tokens": "^9.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", - "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", - "dev": true - }, "node_modules/strongly-connected-components": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz", "integrity": "sha512-i0TFx4wPcO0FwX+4RkLJi1MxmcTv90jNZgxMu9XRnMXMeFUY1VJlIoXpZunPUvUUqbCT1pg5PEkFqqpcaElNaA==" }, + "node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.27.0" + } + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -12404,20 +13104,25 @@ "kdbush": "^3.0.0" } }, + "node_modules/supercluster/node_modules/kdbush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", + "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==" + }, "node_modules/superscript-text": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/superscript-text/-/superscript-text-1.0.0.tgz", "integrity": "sha512-gwu8l5MtRZ6koO0icVTlmN5pm7Dhh1+Xpe9O4x6ObMAsW+3jPbW14d1DsBq1F4wiI+WOFjXF35pslgec/G8yCQ==" }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -12468,46 +13173,54 @@ } }, "node_modules/swagger-client": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.25.0.tgz", - "integrity": "sha512-p143zWkIhgyh2E5+3HPFMlCw3WkV9RbX9HyftfBdiccCbOlmHdcJC0XEJZxcm+ZA+80DORs0F30/mzk7sx4iwA==", + "version": "3.29.3", + "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.29.3.tgz", + "integrity": "sha512-OhhMAO2dwDEaxtUNDxwaqzw75uiZY5lX/2vx+U6eKCYZYhXWQ5mylU/0qfk/xMR20VyitsnzRc6KcFFjRoCS7A==", "dependencies": { "@babel/runtime-corejs3": "^7.22.15", - "@swagger-api/apidom-core": ">=0.90.0 <1.0.0", - "@swagger-api/apidom-error": ">=0.90.0 <1.0.0", - "@swagger-api/apidom-json-pointer": ">=0.90.0 <1.0.0", - "@swagger-api/apidom-ns-openapi-3-1": ">=0.90.0 <1.0.0", - "@swagger-api/apidom-reference": ">=0.90.0 <1.0.0", + "@swagger-api/apidom-core": ">=1.0.0-alpha.9 <1.0.0-beta.0", + "@swagger-api/apidom-error": ">=1.0.0-alpha.9 <1.0.0-beta.0", + "@swagger-api/apidom-json-pointer": ">=1.0.0-alpha.9 <1.0.0-beta.0", + "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-alpha.9 <1.0.0-beta.0", + "@swagger-api/apidom-reference": ">=1.0.0-alpha.9 <1.0.0-beta.0", "cookie": "~0.6.0", "deepmerge": "~4.3.0", "fast-json-patch": "^3.0.0-1", - "is-plain-object": "^5.0.0", "js-yaml": "^4.1.0", + "neotraverse": "=0.6.18", "node-abort-controller": "^3.1.1", - "node-fetch-commonjs": "^3.3.1", - "qs": "^6.10.2", - "traverse": "~0.6.6", - "undici": "^5.24.0" + "node-fetch-commonjs": "^3.3.2", + "openapi-path-templating": "^1.5.1", + "openapi-server-url-templating": "^1.0.0", + "ramda": "^0.30.1", + "ramda-adjunct": "^5.0.0" + } + }, + "node_modules/swagger-client/node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" } }, "node_modules/swagger-ui-react": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-5.9.0.tgz", - "integrity": "sha512-j45ceuGHMRmI8nhOaG71VeQwrPutFHDq6QhgrxOmf4BRMOdOQgVY1POQY9ksnXZtskbD9J2NHURs4BLEDIs8gA==", + "version": "5.17.14", + "resolved": "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-5.17.14.tgz", + "integrity": "sha512-mCXerZrbcn4ftPYifUF0+iKIRTHoVCv0HcJc/sXl9nCe3oeWdsjmOWVqKabzzAkAa0NwsbKNJFv2UL/Ivnf6VQ==", "dependencies": { - "@babel/runtime-corejs3": "^7.23.1", - "@braintree/sanitize-url": "=6.0.4", + "@babel/runtime-corejs3": "^7.24.5", + "@braintree/sanitize-url": "=7.0.2", "base64-js": "^1.5.1", - "classnames": "^2.3.1", + "classnames": "^2.5.1", "css.escape": "1.5.1", "deep-extend": "0.6.0", - "dompurify": "=3.0.6", + "dompurify": "=3.1.4", "ieee754": "^1.2.1", "immutable": "^3.x.x", "js-file-download": "^0.4.12", "js-yaml": "=4.1.0", "lodash": "^4.17.21", - "patch-package": "^8.0.0", "prop-types": "^15.8.1", "randexp": "^0.5.3", "randombytes": "^2.1.0", @@ -12516,29 +13229,29 @@ "react-immutable-proptypes": "2.2.0", "react-immutable-pure-component": "^2.2.0", "react-inspector": "^6.0.1", - "react-redux": "^8.1.2", + "react-redux": "^9.1.2", "react-syntax-highlighter": "^15.5.0", - "redux": "^4.1.2", + "redux": "^5.0.1", "redux-immutable": "^4.0.0", "remarkable": "^2.0.1", - "reselect": "^4.1.8", + "reselect": "^5.1.0", "serialize-error": "^8.1.0", "sha.js": "^2.4.11", - "swagger-client": "^3.22.3", + "swagger-client": "^3.28.1", "url-parse": "^1.5.10", "xml": "=1.0.1", "xml-but-prettier": "^1.0.1", "zenscroll": "^4.0.2" }, "peerDependencies": { - "react": ">=17.0.0", - "react-dom": ">=17.0.0" + "react": ">=16.8.0 <19", + "react-dom": ">=16.8.0 <19" } }, "node_modules/swagger-ui-react/node_modules/dompurify": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", - "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.4.tgz", + "integrity": "sha512-2gnshi6OshmuKil8rMZuQCGiUF3cUxHY3NGDzUAdUx/NPEe5DVnO8BDoAQouvgwnx0R/+a6jUn36Z0FSdq8vww==" }, "node_modules/swagger-ui-react/node_modules/immutable": { "version": "3.8.2", @@ -12548,6 +13261,33 @@ "node": ">=0.10.0" } }, + "node_modules/swagger-ui-react/node_modules/react-redux": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", + "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", + "dependencies": { + "@types/use-sync-external-store": "^0.0.3", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25", + "react": "^18.0", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/swagger-ui-react/node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + }, "node_modules/swagger-ui-react/node_modules/redux-immutable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz", @@ -12556,6 +13296,11 @@ "immutable": "^3.8.1 || ^4.0.0-rc.1" } }, + "node_modules/swagger-ui-react/node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -12563,9 +13308,9 @@ "dev": true }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -12578,6 +13323,15 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -12631,18 +13385,90 @@ "node": ">= 6" } }, + "node_modules/terser": { + "version": "5.34.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.1.tgz", + "integrity": "sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==", + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, "engines": { - "node": ">=8" + "node": ">=18" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/text-table": { @@ -12675,14 +13501,14 @@ "optional": true }, "node_modules/tiny-invariant": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", - "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, "node_modules/tinybench": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", - "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true }, "node_modules/tinycolor2": { @@ -12690,13 +13516,58 @@ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true + }, + "node_modules/tinyglobby": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.6.tgz", + "integrity": "sha512-NbBoFBpqfcgd1tCiO8Lkfdk+xrA7mlLR9zgvZcZWQQwU63XAfUePyd6wZBaU93Hqw347lHnwFzttAkemHzzz4g==", + "dev": true, + "dependencies": { + "fdir": "^6.3.0", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.3.0.tgz", + "integrity": "sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==", + "dev": true, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", "dev": true, "engines": { - "node": ">=14.0.0" + "node": "^18.0.0 || >=20.0.0" } }, "node_modules/tinyqueue": { @@ -12704,26 +13575,42 @@ "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", "dev": true, "engines": { "node": ">=14.0.0" } }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/tldts": { + "version": "6.1.48", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz", + "integrity": "sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==", + "dev": true, "dependencies": { - "os-tmpdir": "~1.0.2" + "tldts-core": "^6.1.48" }, - "engines": { - "node": ">=0.6.0" + "bin": { + "tldts": "bin/cli.js" } }, + "node_modules/tldts-core": { + "version": "6.1.48", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.48.tgz", + "integrity": "sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==", + "dev": true + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -12749,6 +13636,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -12784,43 +13672,27 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dev": true, "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" + "node": ">=16" } }, "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/traverse": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", - "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", - "engines": { - "node": ">= 0.4" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=18" } }, "node_modules/tree-sitter": { @@ -12835,9 +13707,9 @@ } }, "node_modules/tree-sitter-json": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.20.1.tgz", - "integrity": "sha512-482hf7J+aBwhksSw8yWaqI8nyP1DrSwnS4IMBShsnkFWD3SE8oalHnsEik59fEVi3orcTCUtMzSjZx+0Tpa6Vw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.20.2.tgz", + "integrity": "sha512-eUxrowp4F1QEGk/i7Sa+Xl8Crlfp7J0AXxX1QdJEQKQYMWhgMbCIgyQvpO3Q0P9oyTrNQxRLlRipDS44a8EtRw==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -12855,12 +13727,12 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -12883,10 +13755,9 @@ } }, "node_modules/ts-mixer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", - "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==", - "optional": true + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" }, "node_modules/ts-toolbelt": { "version": "9.6.0", @@ -12894,9 +13765,9 @@ "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==" }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -12911,9 +13782,9 @@ } }, "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==" }, "node_modules/type-check": { "version": "0.4.0", @@ -12927,15 +13798,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -12948,29 +13810,30 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -12980,16 +13843,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -12999,14 +13863,20 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13027,17 +13897,17 @@ } }, "node_modules/types-ramda": { - "version": "0.29.7", - "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.7.tgz", - "integrity": "sha512-8KBxZGJwUF3MpRkkJauSpvfHXk8Ssq15QXGuCBTDGeKd9PfheokkC3wAKRV3djej9O31Qa5M7Owsg8hF0GjtAw==", + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.30.1.tgz", + "integrity": "sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA==", "dependencies": { "ts-toolbelt": "^9.6.0" } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -13047,10 +13917,23 @@ "node": ">=14.17" } }, + "node_modules/typewise": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", + "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", + "dependencies": { + "typewise-core": "^1.2.0" + } + }, + "node_modules/typewise-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", + "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==" + }, "node_modules/ua-parser-js": { - "version": "0.7.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", - "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", + "version": "0.7.39", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.39.tgz", + "integrity": "sha512-IZ6acm6RhQHNibSt7+c09hhvsKy9WUr4DVbeq9U8o71qxyYtJpQeDxQnMrVqnIFMLcQjHO0I9wgfO2vIahht4w==", "funding": [ { "type": "opencollective", @@ -13065,16 +13948,13 @@ "url": "https://github.com/sponsors/faisalman" } ], + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { "node": "*" } }, - "node_modules/ufo": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", - "dev": true - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -13090,32 +13970,31 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici": { - "version": "5.28.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.2.tgz", - "integrity": "sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==", + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dependencies": { - "@fastify/busboy": "^2.0.0" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" }, "engines": { - "node": ">=14.0" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" + "node": ">=0.10.0" } }, - "node_modules/unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", - "optional": true, + "node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "engines": { - "node": ">= 0.4.0" + "node": ">=0.10.0" } }, "node_modules/unquote": { @@ -13129,9 +14008,9 @@ "integrity": "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg==" }, "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -13147,8 +14026,8 @@ } ], "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -13225,9 +14104,9 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -13247,9 +14126,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -13259,22 +14138,22 @@ } }, "node_modules/vanilla-picker": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.2.tgz", - "integrity": "sha512-dk0gNeNL9fQFGd1VEhNDQfFlbCqAiksRh1H2tVPlavkH88n/a/y30rXi9PPKrYPTK5kEfPO4xcldt4ts/1wIAg==", + "version": "2.12.3", + "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.3.tgz", + "integrity": "sha512-qVkT1E7yMbUsB2mmJNFmaXMWE2hF8ffqzMMwe9zdAikd8u2VfnsVY2HQcOUi2F38bgbxzlJBEdS1UUhOXdF9GQ==", "dependencies": { "@sphinxxxx/color-conversion": "^2.2.2" } }, "node_modules/vite": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.8.tgz", - "integrity": "sha512-jYMALd8aeqR3yS9xlHd0OzQJndS9fH5ylVgWdB+pxTwxLKdO1pgC5Dlb398BUxpfaBxa4M9oT7j1g503Gaj5IQ==", + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", "dev": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.32", - "rollup": "^4.2.0" + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -13293,6 +14172,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -13310,6 +14190,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -13322,15 +14205,14 @@ } }, "node_modules/vite-node": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", - "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", + "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", "dev": true, "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", + "debug": "^4.3.6", + "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { @@ -13344,31 +14226,30 @@ } }, "node_modules/vitest": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", - "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", - "dev": true, - "dependencies": { - "@vitest/expect": "1.6.0", - "@vitest/runner": "1.6.0", - "@vitest/snapshot": "1.6.0", - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", + "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "dev": true, + "dependencies": { + "@vitest/expect": "2.1.1", + "@vitest/mocker": "2.1.1", + "@vitest/pretty-format": "^2.1.1", + "@vitest/runner": "2.1.1", + "@vitest/snapshot": "2.1.1", + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "debug": "^4.3.6", + "magic-string": "^0.30.11", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "1.6.0", - "why-is-node-running": "^2.2.2" + "vite-node": "2.1.1", + "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" @@ -13382,8 +14263,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.6.0", - "@vitest/ui": "1.6.0", + "@vitest/browser": "2.1.1", + "@vitest/ui": "2.1.1", "happy-dom": "*", "jsdom": "*" }, @@ -13438,15 +14319,28 @@ "node": ">=18" } }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/weak-map": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.8.tgz", "integrity": "sha512-lNR9aAefbGPpHO7AEnY0hCFjz1eTkWCXYvkTRrTHs9qv8zJp+SkVYpzfLIFXQQiG3tVvbNFQgVg2bQS8YGgxyw==" }, "node_modules/web-streams-polyfill": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", - "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "engines": { "node": ">= 8" } @@ -13466,9 +14360,90 @@ } }, "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack": { + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", + "peer": true, + "dependencies": { + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "peer": true, + "engines": { + "node": ">=4.0" + } }, "node_modules/whatwg-encoding": { "version": "3.1.1", @@ -13504,18 +14479,23 @@ } }, "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -13543,13 +14523,13 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -13558,8 +14538,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -13569,31 +14549,34 @@ } }, "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13603,9 +14586,9 @@ } }, "node_modules/why-is-node-running": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", - "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "dependencies": { "siginfo": "^2.0.0", @@ -13618,6 +14601,15 @@ "node": ">=8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/world-calendars": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/world-calendars/-/world-calendars-1.0.3.tgz", @@ -13626,15 +14618,142 @@ "object-assign": "^4.1.0" } }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "engines": { "node": ">=10.0.0" @@ -13700,9 +14819,9 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { "version": "1.10.2", diff --git a/webapp/package.json b/webapp/package.json index 0cac1710ac..da78848498 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -1,132 +1,134 @@ { "name": "antares-web", - "version": "2.17.5", + "version": "2.17.6", "private": true, "type": "module", "scripts": { "build": "tsc && vite build", "clean": "rm -rf dist node_modules/.vite", + "coverage": "vitest run --coverage", "dev": "vite", "lint": "tsc --noEmit && eslint . --ext ts,tsx --report-unused-disable-directives", "preview": "vite preview", "test": "vitest", - "test:ui": "vitest --ui", - "coverage": "vitest run --coverage" + "test:ui": "vitest --ui" }, "dependencies": { - "@emotion/react": "11.11.1", - "@emotion/styled": "11.11.0", + "@emotion/react": "11.13.3", + "@emotion/styled": "11.13.0", "@glideapps/glide-data-grid": "6.0.3", - "@handsontable/react": "14.1.0", - "@mui/icons-material": "5.14.11", - "@mui/lab": "5.0.0-alpha.146", - "@mui/material": "5.14.11", - "@mui/x-date-pickers": "6.18.3", + "@handsontable/react": "14.5.0", + "@mui/icons-material": "6.1.1", + "@mui/lab": "6.0.0-beta.10", + "@mui/material": "6.1.1", + "@mui/x-tree-view": "7.18.0", "@reduxjs/toolkit": "1.9.6", - "axios": "1.5.1", - "clsx": "2.0.0", + "axios": "1.7.7", + "clsx": "2.1.1", "d3": "5.16.0", - "debug": "4.3.4", + "debug": "4.3.7", "draft-convert": "2.1.13", "draft-js": "0.11.7", "draftjs-to-html": "0.9.1", - "handsontable": "14.1.0", + "handsontable": "14.5.0", "hoist-non-react-statics": "3.3.2", - "i18next": "23.5.1", - "i18next-browser-languagedetector": "7.1.0", - "i18next-http-backend": "2.4.2", - "immer": "10.0.3", + "i18next": "23.15.1", + "i18next-browser-languagedetector": "8.0.0", + "i18next-http-backend": "2.6.1", + "immer": "10.1.1", "js-cookie": "3.0.5", - "jsoneditor": "9.10.4", - "jwt-decode": "3.1.2", + "jsoneditor": "10.1.0", + "jwt-decode": "4.0.0", "lodash": "4.17.21", - "material-react-table": "2.0.5", - "moment": "2.29.4", + "material-react-table": "3.0.1", + "moment": "2.30.1", "notistack": "3.0.1", - "plotly.js": "2.26.1", - "ramda": "0.29.0", - "ramda-adjunct": "4.1.1", - "react": "18.2.0", + "plotly.js": "2.35.2", + "ramda": "0.30.1", + "ramda-adjunct": "5.1.0", + "react": "18.3.1", "react-beautiful-dnd": "13.1.1", "react-color": "2.19.3", "react-d3-graph": "2.6.0", - "react-dom": "18.2.0", + "react-dom": "18.3.1", "react-dropzone": "14.2.3", - "react-hook-form": "7.47.0", - "react-i18next": "13.2.2", + "react-hook-form": "7.53.0", + "react-i18next": "15.0.2", "react-json-view": "1.21.3", "react-plotly.js": "2.6.0", "react-redux": "8.1.3", "react-router": "6.3.0", "react-router-dom": "6.3.0", "react-split": "2.0.14", - "react-use": "17.4.0", - "react-virtualized-auto-sizer": "1.0.20", - "react-window": "1.8.9", + "react-syntax-highlighter": "15.5.0", + "react-use": "17.5.1", + "react-virtualized-auto-sizer": "1.0.24", + "react-window": "1.8.10", "redux": "4.2.1", "redux-thunk": "2.4.2", - "swagger-ui-react": "5.9.0", + "swagger-ui-react": "5.17.14", "ts-toolbelt": "9.6.0", "use-undo": "1.1.1", - "uuid": "9.0.1", + "uuid": "10.0.0", "xml-js": "1.6.11" }, "devDependencies": { - "@testing-library/jest-dom": "6.4.6", - "@testing-library/react": "16.0.0", + "@testing-library/jest-dom": "6.5.0", + "@testing-library/react": "16.0.1", "@testing-library/user-event": "14.5.2", - "@total-typescript/ts-reset": "0.5.1", + "@total-typescript/ts-reset": "0.6.1", "@types/d3": "5.16.0", - "@types/debug": "4.1.9", - "@types/draft-convert": "2.1.5", - "@types/draft-js": "0.11.13", - "@types/draftjs-to-html": "0.8.2", - "@types/js-cookie": "3.0.4", + "@types/debug": "4.1.12", + "@types/draft-convert": "2.1.8", + "@types/draft-js": "0.11.18", + "@types/draftjs-to-html": "0.8.4", + "@types/js-cookie": "3.0.6", "@types/jsoneditor": "9.9.5", - "@types/lodash": "4.14.199", - "@types/node": "18.16.1", - "@types/ramda": "0.29.5", - "@types/react": "18.2.24", - "@types/react-beautiful-dnd": "13.1.5", - "@types/react-color": "3.0.7", + "@types/lodash": "4.17.9", + "@types/node": "22.7.3", + "@types/ramda": "0.30.2", + "@types/react": "18.3.9", + "@types/react-beautiful-dnd": "13.1.8", + "@types/react-color": "3.0.12", "@types/react-d3-graph": "2.6.5", - "@types/react-dom": "18.2.8", - "@types/react-plotly.js": "2.6.1", - "@types/react-virtualized-auto-sizer": "1.0.1", - "@types/react-window": "1.8.6", - "@types/redux-logger": "3.0.10", - "@types/swagger-ui-react": "4.18.1", + "@types/react-dom": "18.3.0", + "@types/react-plotly.js": "2.6.3", + "@types/react-syntax-highlighter": "15.5.13", + "@types/react-virtualized-auto-sizer": "1.0.4", + "@types/react-window": "1.8.8", + "@types/swagger-ui-react": "4.18.3", "@types/testing-library__jest-dom": "6.0.0", - "@types/uuid": "9.0.4", - "@typescript-eslint/eslint-plugin": "6.14.0", - "@typescript-eslint/parser": "6.14.0", - "@vitejs/plugin-react-swc": "3.5.0", - "@vitest/coverage-v8": "1.6.0", - "@vitest/ui": "1.6.0", - "eslint": "8.55.0", - "eslint-config-prettier": "9.0.0", - "eslint-plugin-jsdoc": "48.2.0", - "eslint-plugin-prettier": "5.0.0", - "eslint-plugin-react": "7.33.2", - "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-react-refresh": "0.4.5", - "husky": "8.0.3", - "jsdom": "24.1.0", - "prettier": "3.0.3", - "typescript": "5.2.2", - "vite": "5.0.8", - "vitest": "1.6.0" + "@types/uuid": "10.0.0", + "@typescript-eslint/eslint-plugin": "7.2.0", + "@typescript-eslint/parser": "7.2.0", + "@vitejs/plugin-react-swc": "3.7.0", + "@vitest/coverage-v8": "2.1.1", + "@vitest/ui": "2.1.1", + "eslint": "8.57.1", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-jsdoc": "48.10.0", + "eslint-plugin-license-header": "0.6.1", + "eslint-plugin-prettier": "5.2.1", + "eslint-plugin-react": "7.37.0", + "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-refresh": "0.4.12", + "husky": "9.1.6", + "jsdom": "25.0.1", + "prettier": "3.3.3", + "typescript": "5.4.5", + "vite": "5.4.8", + "vitest": "2.1.1" }, "engines": { "node": "18.16.1" }, "overrides": { "react-d3-graph": { - "react": "18.2.0" + "react": "18.3.1" }, "react-json-view": { - "react": "18.2.0", - "react-dom": "18.2.0" + "react": "18.3.1", + "react-dom": "18.3.1" } } } diff --git a/webapp/public/locales/en/main.json b/webapp/public/locales/en/main.json index f839e170eb..f4d3c0eb93 100644 --- a/webapp/public/locales/en/main.json +++ b/webapp/public/locales/en/main.json @@ -10,6 +10,7 @@ "global.archive": "Archive", "global.unarchive": "Unarchive", "global.export": "Export", + "global.export.error": "Export failed", "global.filter": "Filter", "global.apply": "Apply", "global.change": "Change", @@ -34,6 +35,8 @@ "global.import": "Import", "global.import.fromFile": "From a file", "global.import.fromDatabase": "From database", + "global.import.success": "Import successful", + "global.import.error": "Import failed", "global.launch": "Launch", "global.jobs": "Jobs", "global.unknown": "Unknown", @@ -49,7 +52,6 @@ "global.emptyString": "Empty string", "global.edit": "Edit", "global.download": "Download", - "global.download.error": "Download failed", "global.generate": "Generate", "global.user": "User", "global.users": "Users", @@ -72,6 +74,7 @@ "global.total": "Total", "global.enabled": "Enabled", "global.close": "Close", + "global.replace": "Replace", "global.time.hourly": "Hourly", "global.time.daily": "Daily", "global.time.weekly": "Weekly", @@ -88,6 +91,7 @@ "global.error.delete": "Deletion failed", "global.area.add": "Add an area", "global.add": "Add", + "global.timeSeries": "Time Series", "login.error": "Failed to authenticate", "tasks.title": "Tasks", "api.title": "API", @@ -239,6 +243,13 @@ "study.district": "District", "study.bindingconstraints": "Binding Constraints", "study.debug": "Debug", + "study.debug.file.image": "Image file", + "study.debug.file.deleteConfirm.title": "Delete File?", + "study.debug.file.deleteConfirm.message": "Are you sure you want to delete the file?", + "study.debug.folder.empty": "Folder is empty", + "study.debug.folder.upload.replaceFileConfirm.title": "Replace File?", + "study.debug.folder.upload.replaceFileConfirm.message": "Another file with the same name already exists. Replacing it will overwrite its content.", + "study.debug.folder.upload.error.replaceFolder": "A folder with the same name already exists and cannot be replaced by a file", "study.failtofetchlogs": "Failed to fetch logs", "study.failtokilltask": "Failed to kill task", "study.publicMode": "Public mode", @@ -443,16 +454,16 @@ "study.modelization.hydro.allocation.viewMatrix": "View all allocations", "study.modelization.hydro.allocation.error.field.delete": "Error when deleting the allocation", "study.modelization.storages": "Storages", - "study.modelization.storages.modulation": "Injection / Withdrawal Modulation", + "study.modelization.storages.modulation": "Stored / Released Modulation", "study.modelization.storages.ruleCurves": "Rule Curves", "study.modelization.storages.inflows": "Inflows", - "study.modelization.storages.injectionModulation": "Injection Modulation", - "study.modelization.storages.withdrawalModulation": "Withdrawal Modulation", + "study.modelization.storages.injectionModulation": "Stored Modulation", + "study.modelization.storages.withdrawalModulation": "Released Modulation", "study.modelization.storages.lowerRuleCurve": "Lower rule curve", "study.modelization.storages.upperRuleCurve": "Upper rule curve", - "study.modelization.storages.injectionNominalCapacity": "Injection (MW)", + "study.modelization.storages.injectionNominalCapacity": "Stored (MW)", "study.modelization.storages.injectionNominalCapacity.info": "Injection capacity from stock to the network (MW)", - "study.modelization.storages.withdrawalNominalCapacity": "Withdrawal (MW)", + "study.modelization.storages.withdrawalNominalCapacity": "Released (MW)", "study.modelization.storages.withdrawalNominalCapacity.info": "Withdrawal capacity from the network (MW)", "study.modelization.storages.reservoirCapacity": "Stock (MWh)", "study.modelization.storages.reservoirCapacity.info": "Stock (MWh)", diff --git a/webapp/public/locales/fr/main.json b/webapp/public/locales/fr/main.json index 2b8bcd3cbf..3062419fea 100644 --- a/webapp/public/locales/fr/main.json +++ b/webapp/public/locales/fr/main.json @@ -10,6 +10,7 @@ "global.archive": "Archiver", "global.unarchive": "Désarchiver", "global.export": "Exporter", + "global.export.error": "L'export a échoué", "global.filter": "Filtrer", "global.apply": "Appliquer", "global.change": "Changer", @@ -34,6 +35,8 @@ "global.import": "Importer", "global.import.fromFile": "Depuis un fichier", "global.import.fromDatabase": "Depuis la base de donnée", + "global.import.success": "Importation réussie", + "global.import.error": "Échec de l'importation", "global.launch": "Lancer", "global.jobs": "Tâches", "global.unknown": "Inconnu", @@ -49,7 +52,6 @@ "global.emptyString": "Chaine de caractères vide", "global.edit": "Editer", "global.download": "Télécharger", - "global.download.error": "Le téléchargement a échoué", "global.generate": "Générer", "global.user": "Utilisateur", "global.users": "Utilisateurs", @@ -72,6 +74,7 @@ "global.total": "Total", "global.enabled": "Activé", "global.close": "Fermer", + "global.replace": "Remplacer", "global.time.hourly": "Horaire", "global.time.daily": "Journalier", "global.time.weekly": "Hebdomadaire", @@ -88,6 +91,7 @@ "global.error.delete": "La suppression a échoué", "global.area.add": "Ajouter une zone", "global.add": "Ajouter", + "global.timeSeries": "Séries temporelles", "login.error": "Échec de l'authentification", "tasks.title": "Tâches", "api.title": "API", @@ -239,6 +243,13 @@ "study.district": "District", "study.bindingconstraints": "Contraintes Couplantes", "study.debug": "Debug", + "study.debug.file.image": "Fichier image", + "study.debug.folder.empty": "Le dossier est vide", + "study.debug.file.deleteConfirm.title": "Supprimer le fichier ?", + "study.debug.file.deleteConfirm.message": "Êtes-vous sûr de vouloir supprimer le fichier ?", + "study.debug.folder.upload.replaceFileConfirm.title": "Remplacer le fichier ?", + "study.debug.folder.upload.replaceFileConfirm.message": "Un autre fichier du même nom existe déjà. Le remplacer écrasera son contenu.", + "study.debug.folder.upload.error.replaceFolder": "Un dossier du même nom existe déjà et ne peut pas être remplacé par un fichier", "study.failtofetchlogs": "Échec du chargement des logs", "study.failtokilltask": "Échec de l'annulation de l'étude", "study.publicMode": "Mode public", @@ -443,16 +454,16 @@ "study.modelization.hydro.allocation.viewMatrix": "Voir les allocations", "study.modelization.hydro.allocation.error.field.delete": "Erreur lors de la suppression de l'allocation", "study.modelization.storages": "Stockages", - "study.modelization.storages.modulation": "Modulation de l’injection / soutirage", + "study.modelization.storages.modulation": "Modulation du stockage / déstockage", "study.modelization.storages.ruleCurves": "Courbe guides", "study.modelization.storages.inflows": "Apports", - "study.modelization.storages.injectionModulation": "Modulation de l’injection", - "study.modelization.storages.withdrawalModulation": "Modulation du soutirage", + "study.modelization.storages.injectionModulation": "Modulation du stockage", + "study.modelization.storages.withdrawalModulation": "Modulation du déstockage", "study.modelization.storages.lowerRuleCurve": "Courbe guide inférieure", "study.modelization.storages.upperRuleCurve": "Courbe guide supérieure", - "study.modelization.storages.injectionNominalCapacity": "Injection (MW)", + "study.modelization.storages.injectionNominalCapacity": "Stockage (MW)", "study.modelization.storages.injectionNominalCapacity.info": "Capacité d’injection dans le stock depuis le réseau (MW)", - "study.modelization.storages.withdrawalNominalCapacity": "Soutirage (MW)", + "study.modelization.storages.withdrawalNominalCapacity": "Déstockage (MW)", "study.modelization.storages.withdrawalNominalCapacity.info": "Capacité de soutirage du stock vers le réseau (MW)", "study.modelization.storages.reservoirCapacity": "Stock (MWh)", "study.modelization.storages.reservoirCapacity.info": "Stock (MWh)", @@ -753,7 +764,7 @@ "data.message.uploadHelp": "Le fichier doit être une matrice simple ou un zip contenant à plat des fichiers de matrices", "results.error.jobs": "Erreur lors de la récupération des tâches de lancement", "results.error.outputs": "Erreur lors de la récupération des sorties de l'étude", - "results.noOutputs": "Aucune sorties", + "results.noOutputs": "Aucune sortie", "results.question.deleteOutput": "Êtes-vous sûr de vouloir supprimer le résultat de simulation {{outputname}} ?", "tableMode.type.areas": "Zones", "tableMode.type.links": "Liens", diff --git a/webapp/src/common/types.ts b/webapp/src/common/types.ts index 7e62f614e4..20893f0abe 100644 --- a/webapp/src/common/types.ts +++ b/webapp/src/common/types.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ReactNode } from "react"; export type IdType = number | string; diff --git a/webapp/src/components/App/Api.tsx b/webapp/src/components/App/Api.tsx index 612194c0b1..837b80e729 100644 --- a/webapp/src/components/App/Api.tsx +++ b/webapp/src/components/App/Api.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import SwaggerUI from "swagger-ui-react"; import "swagger-ui-react/swagger-ui.css"; diff --git a/webapp/src/components/App/Data/DataListing.tsx b/webapp/src/components/App/Data/DataListing.tsx index bf0ca2bf00..30968f4f30 100644 --- a/webapp/src/components/App/Data/DataListing.tsx +++ b/webapp/src/components/App/Data/DataListing.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { memo } from "react"; import { Typography, Box, styled } from "@mui/material"; import AutoSizer from "react-virtualized-auto-sizer"; diff --git a/webapp/src/components/App/Data/DataPropsView.tsx b/webapp/src/components/App/Data/DataPropsView.tsx index a5684facec..c4b5215cf5 100644 --- a/webapp/src/components/App/Data/DataPropsView.tsx +++ b/webapp/src/components/App/Data/DataPropsView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { MatrixDataSetDTO, MatrixInfoDTO } from "../../../common/types"; import PropertiesView from "../../common/PropertiesView"; diff --git a/webapp/src/components/App/Data/DatasetCreationDialog.tsx b/webapp/src/components/App/Data/DatasetCreationDialog.tsx index c10b1eaaf4..90764a1977 100644 --- a/webapp/src/components/App/Data/DatasetCreationDialog.tsx +++ b/webapp/src/components/App/Data/DatasetCreationDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState, useEffect, forwardRef, ChangeEvent } from "react"; import { Box, diff --git a/webapp/src/components/App/Data/MatrixDialog.tsx b/webapp/src/components/App/Data/MatrixDialog.tsx index df2b14ab99..c02bf8a6c1 100644 --- a/webapp/src/components/App/Data/MatrixDialog.tsx +++ b/webapp/src/components/App/Data/MatrixDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState, useEffect } from "react"; import { AxiosError } from "axios"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Data/index.tsx b/webapp/src/components/App/Data/index.tsx index 8f73e7a0b7..9055a3e2b4 100644 --- a/webapp/src/components/App/Data/index.tsx +++ b/webapp/src/components/App/Data/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState, useEffect } from "react"; import { AxiosError } from "axios"; import { useSnackbar } from "notistack"; @@ -174,9 +188,10 @@ function Data() { lineHeight: 1.334, }} > - {`Matrices - ${dataList.find( - (item) => item.id === selectedItem, - )?.name}`} + {`Matrices - ${ + dataList.find((item) => item.id === selectedItem) + ?.name + }`} @@ -223,9 +238,9 @@ function Data() { alignItems: "center", }} > - {`Matrices - ${dataList.find( - (item) => item.id === selectedItem, - )?.name}`} + {`Matrices - ${ + dataList.find((item) => item.id === selectedItem)?.name + }`} ) } diff --git a/webapp/src/components/App/Data/styles.ts b/webapp/src/components/App/Data/styles.ts index ea28cf1208..fe3be93d6b 100644 --- a/webapp/src/components/App/Data/styles.ts +++ b/webapp/src/components/App/Data/styles.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled, Box, Typography } from "@mui/material"; import DownloadIcon from "@mui/icons-material/Download"; diff --git a/webapp/src/components/App/Data/utils.tsx b/webapp/src/components/App/Data/utils.tsx index 3542b219be..a05c03a790 100644 --- a/webapp/src/components/App/Data/utils.tsx +++ b/webapp/src/components/App/Data/utils.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { GroupDTO, MatrixDataSetDTO, diff --git a/webapp/src/components/App/Settings/Groups/Header.tsx b/webapp/src/components/App/Settings/Groups/Header.tsx index f15dd25eeb..f73f783ef9 100644 --- a/webapp/src/components/App/Settings/Groups/Header.tsx +++ b/webapp/src/components/App/Settings/Groups/Header.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button } from "@mui/material"; import GroupAddIcon from "@mui/icons-material/GroupAdd"; import { useTranslation } from "react-i18next"; @@ -8,20 +22,12 @@ import { isAuthUserAdmin } from "../../../../redux/selectors"; import useAppSelector from "../../../../redux/hooks/useAppSelector"; import SearchFE from "../../../common/fieldEditors/SearchFE"; -/** - * Types - */ - interface Props { setSearchValue: (v: string) => void; addGroup: (user: GroupDetailsDTO) => void; reloadFetchGroups: () => void; } -/** - * Component - */ - function Header(props: Props) { const { setSearchValue, addGroup, reloadFetchGroups } = props; const { t } = useTranslation(); diff --git a/webapp/src/components/App/Settings/Groups/dialog/CreateGroupDialog.tsx b/webapp/src/components/App/Settings/Groups/dialog/CreateGroupDialog.tsx index dd99768fce..3b3abd1485 100644 --- a/webapp/src/components/App/Settings/Groups/dialog/CreateGroupDialog.tsx +++ b/webapp/src/components/App/Settings/Groups/dialog/CreateGroupDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import GroupAddIcon from "@mui/icons-material/GroupAdd"; import { useSnackbar } from "notistack"; import { useTranslation } from "react-i18next"; @@ -13,10 +27,6 @@ import { createGroup, createRole } from "../../../../../services/api/user"; import { SubmitHandlerPlus } from "../../../../common/Form/types"; import GroupFormDialog, { GroupFormDialogProps } from "./GroupFormDialog"; -/** - * Types - */ - type InheritPropsToOmit = "title" | "titleIcon" | "onSubmit" | "onCancel"; interface Props extends Omit { @@ -25,10 +35,6 @@ interface Props extends Omit { closeDialog: VoidFunction; } -/** - * Component - */ - function CreateGroupDialog(props: Props) { const { addGroup, reloadFetchGroups, closeDialog, ...dialogProps } = props; const { enqueueSnackbar } = useSnackbar(); diff --git a/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx b/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx index 39e8e26ca4..9027ee1bcd 100644 --- a/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx +++ b/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useMemo, useRef, useState } from "react"; import { diff --git a/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/index.tsx b/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/index.tsx index 26ea1d5b65..ef29ca1722 100644 --- a/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/index.tsx +++ b/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/index.tsx @@ -1,13 +1,23 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import FormDialog, { FormDialogProps, } from "../../../../../common/dialogs/FormDialog"; import { RoleType, UserDTO } from "../../../../../../common/types"; import GroupForm from "./GroupForm"; -/** - * Types - */ - export interface GroupFormDialogProps extends Omit { defaultValues?: { @@ -16,10 +26,6 @@ export interface GroupFormDialogProps }; } -/** - * Component - */ - function GroupFormDialog(props: GroupFormDialogProps) { const { defaultValues, ...dialogProps } = props; @@ -30,8 +36,4 @@ function GroupFormDialog(props: GroupFormDialogProps) { ); } -GroupFormDialog.defaultProps = { - defaultValues: undefined, -}; - export default GroupFormDialog; diff --git a/webapp/src/components/App/Settings/Groups/dialog/UpdateGroupDialog.tsx b/webapp/src/components/App/Settings/Groups/dialog/UpdateGroupDialog.tsx index 2a85371138..42e4541ed9 100644 --- a/webapp/src/components/App/Settings/Groups/dialog/UpdateGroupDialog.tsx +++ b/webapp/src/components/App/Settings/Groups/dialog/UpdateGroupDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import EditIcon from "@mui/icons-material/Edit"; import { useMemo } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Settings/Groups/index.tsx b/webapp/src/components/App/Settings/Groups/index.tsx index b662134427..b92e62ffe8 100644 --- a/webapp/src/components/App/Settings/Groups/index.tsx +++ b/webapp/src/components/App/Settings/Groups/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, CircularProgress, @@ -33,10 +47,6 @@ import { getAuthUser } from "../../../../redux/selectors"; import useAppSelector from "../../../../redux/hooks/useAppSelector"; import { isSearchMatching } from "../../../../utils/stringUtils"; -/** - * Types - */ - enum GroupActionKind { ADD = "ADD", EDIT = "EDIT", @@ -56,10 +66,6 @@ interface GroupAction extends Action { | GroupEdit; } -/** - * Utils - */ - const reducer = produce((draft, action) => { const { payload } = action; @@ -88,10 +94,6 @@ const reducer = produce((draft, action) => { } }); -/** - * Component - */ - function Groups() { const [groupToDelete, setGroupToDelete] = useState(); const [groupToEdit, setGroupToEdit] = useState(); diff --git a/webapp/src/components/App/Settings/Maintenance/index.tsx b/webapp/src/components/App/Settings/Maintenance/index.tsx index 817c7ca690..624006a4e6 100644 --- a/webapp/src/components/App/Settings/Maintenance/index.tsx +++ b/webapp/src/components/App/Settings/Maintenance/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Backdrop, Box, diff --git a/webapp/src/components/App/Settings/Tokens/Header.tsx b/webapp/src/components/App/Settings/Tokens/Header.tsx index cf1a6e3932..0cf3d3e329 100644 --- a/webapp/src/components/App/Settings/Tokens/Header.tsx +++ b/webapp/src/components/App/Settings/Tokens/Header.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button } from "@mui/material"; import TokenIcon from "@mui/icons-material/Token"; import { useTranslation } from "react-i18next"; @@ -6,20 +20,12 @@ import { BotDTO } from "../../../../common/types"; import CreateTokenDialog from "./dialog/CreateTokenDialog"; import SearchFE from "../../../common/fieldEditors/SearchFE"; -/** - * Types - */ - interface Props { setSearchValue: (v: string) => void; addToken: (user: BotDTO) => void; reloadFetchTokens: () => void; } -/** - * Component - */ - function Header(props: Props) { const { setSearchValue, addToken, reloadFetchTokens } = props; const { t } = useTranslation(); diff --git a/webapp/src/components/App/Settings/Tokens/dialog/CreateTokenDialog.tsx b/webapp/src/components/App/Settings/Tokens/dialog/CreateTokenDialog.tsx index 44e0ebbf33..c735ddb702 100644 --- a/webapp/src/components/App/Settings/Tokens/dialog/CreateTokenDialog.tsx +++ b/webapp/src/components/App/Settings/Tokens/dialog/CreateTokenDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import TokenIcon from "@mui/icons-material/Token"; import { IconButton, Paper, Tooltip } from "@mui/material"; import { useSnackbar } from "notistack"; diff --git a/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/TokenForm.tsx b/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/TokenForm.tsx index 128d963bde..08b8fa928c 100644 --- a/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/TokenForm.tsx +++ b/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/TokenForm.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, @@ -242,9 +256,4 @@ function TokenForm(props: Props) { ); } -TokenForm.defaultProps = { - onlyPermissions: false, - readOnly: false, -}; - export default TokenForm; diff --git a/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/index.tsx b/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/index.tsx index 6da35bd3ad..24516f6b7e 100644 --- a/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/index.tsx +++ b/webapp/src/components/App/Settings/Tokens/dialog/TokenFormDialog/index.tsx @@ -1,21 +1,27 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import FormDialog, { FormDialogProps, } from "../../../../../common/dialogs/FormDialog"; import TokenForm from "./TokenForm"; -/** - * Types - */ - export interface TokenFormDialogProps extends Omit { onlyPermissions?: boolean; } -/** - * Component - */ - function TokenFormDialog(props: TokenFormDialogProps) { const { onlyPermissions, ...dialogProps } = props; @@ -28,8 +34,4 @@ function TokenFormDialog(props: TokenFormDialogProps) { ); } -TokenFormDialog.defaultProps = { - onlyPermissions: false, -}; - export default TokenFormDialog; diff --git a/webapp/src/components/App/Settings/Tokens/dialog/TokenInfoDialog.tsx b/webapp/src/components/App/Settings/Tokens/dialog/TokenInfoDialog.tsx index f880eeae74..23f12dc088 100644 --- a/webapp/src/components/App/Settings/Tokens/dialog/TokenInfoDialog.tsx +++ b/webapp/src/components/App/Settings/Tokens/dialog/TokenInfoDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DialogContentText } from "@mui/material"; import { useTranslation } from "react-i18next"; import InfoIcon from "@mui/icons-material/Info"; @@ -8,18 +22,10 @@ import OkDialog, { OkDialogProps } from "../../../../common/dialogs/OkDialog"; import TokenForm from "./TokenFormDialog/TokenForm"; import Form from "../../../../common/Form"; -/** - * Types - */ - interface Props extends Omit { token: BotDetailsDTO; } -/** - * Component - */ - function TokenInfoDialog(props: Props) { const { token, ...dialogProps } = props; diff --git a/webapp/src/components/App/Settings/Tokens/index.tsx b/webapp/src/components/App/Settings/Tokens/index.tsx index bbbe3d192e..18aa3b4d9a 100644 --- a/webapp/src/components/App/Settings/Tokens/index.tsx +++ b/webapp/src/components/App/Settings/Tokens/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, CircularProgress, @@ -37,10 +51,6 @@ import TokenInfoDialog from "./dialog/TokenInfoDialog"; import useAppSelector from "../../../../redux/hooks/useAppSelector"; import { isSearchMatching } from "../../../../utils/stringUtils"; -/** - * Types - */ - interface BotDetailsDtoWithUser extends BotDetailsDTO { user: UserDTO; } @@ -55,10 +65,6 @@ interface TokenAction extends Action { payload?: BotDTO["id"] | BotDTO | BotDTO[]; } -/** - * Utils - */ - const reducer = produce( (draft, action) => { const { payload } = action; @@ -81,10 +87,6 @@ const reducer = produce( }, ); -/** - * Component - */ - function Tokens() { const [tokenToDisplayInfo, setTokenToDisplayInfo] = useState(); const [tokenToDelete, setTokenToDelete] = useState(); diff --git a/webapp/src/components/App/Settings/Users/Header.tsx b/webapp/src/components/App/Settings/Users/Header.tsx index d8e1a58fb2..47969745bf 100644 --- a/webapp/src/components/App/Settings/Users/Header.tsx +++ b/webapp/src/components/App/Settings/Users/Header.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button } from "@mui/material"; import PersonAddAltIcon from "@mui/icons-material/PersonAddAlt"; import { useTranslation } from "react-i18next"; @@ -6,20 +20,12 @@ import CreateUserDialog from "./dialog/CreateUserDialog"; import { UserDetailsDTO } from "../../../../common/types"; import SearchFE from "../../../common/fieldEditors/SearchFE"; -/** - * Types - */ - interface Props { setSearchValue: (v: string) => void; addUser: (user: UserDetailsDTO) => void; reloadFetchUsers: () => void; } -/** - * Component - */ - function Header(props: Props) { const { setSearchValue, addUser, reloadFetchUsers } = props; const { t } = useTranslation(); diff --git a/webapp/src/components/App/Settings/Users/dialog/CreateUserDialog.tsx b/webapp/src/components/App/Settings/Users/dialog/CreateUserDialog.tsx index cf649266ee..298b7fb84d 100644 --- a/webapp/src/components/App/Settings/Users/dialog/CreateUserDialog.tsx +++ b/webapp/src/components/App/Settings/Users/dialog/CreateUserDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import PersonAddIcon from "@mui/icons-material/PersonAdd"; import { useSnackbar } from "notistack"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Settings/Users/dialog/UpdateUserDialog.tsx b/webapp/src/components/App/Settings/Users/dialog/UpdateUserDialog.tsx index de42dad178..1f8f6afabb 100644 --- a/webapp/src/components/App/Settings/Users/dialog/UpdateUserDialog.tsx +++ b/webapp/src/components/App/Settings/Users/dialog/UpdateUserDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import EditIcon from "@mui/icons-material/Edit"; import { useMemo } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/UserForm.tsx b/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/UserForm.tsx index 59acfc6dc5..9066989aa5 100644 --- a/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/UserForm.tsx +++ b/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/UserForm.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useMemo, useRef, useState } from "react"; import { @@ -252,8 +266,4 @@ function UserForm(props: Props) { ); } -UserForm.defaultProps = { - onlyPermissions: false, -}; - export default UserForm; diff --git a/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/index.tsx b/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/index.tsx index f3d0d915c2..cc2dd19efd 100644 --- a/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/index.tsx +++ b/webapp/src/components/App/Settings/Users/dialog/UserFormDialog/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DialogContentText } from "@mui/material"; import FormDialog, { FormDialogProps, @@ -5,10 +19,6 @@ import FormDialog, { import { GroupDTO, RoleType } from "../../../../../../common/types"; import UserForm from "./UserForm"; -/** - * Types - */ - export interface UserFormDialogProps extends Omit { defaultValues?: { username?: string; @@ -19,10 +29,6 @@ export interface UserFormDialogProps extends Omit { subtitle?: string; } -/** - * Component - */ - function UserFormDialog(props: UserFormDialogProps) { const { defaultValues, onlyPermissions, subtitle, ...dialogProps } = props; @@ -38,10 +44,4 @@ function UserFormDialog(props: UserFormDialogProps) { ); } -UserFormDialog.defaultProps = { - defaultValues: undefined, - onlyPermissions: false, - subtitle: "", -}; - export default UserFormDialog; diff --git a/webapp/src/components/App/Settings/Users/index.tsx b/webapp/src/components/App/Settings/Users/index.tsx index 7af7ee658d..373ca36b84 100644 --- a/webapp/src/components/App/Settings/Users/index.tsx +++ b/webapp/src/components/App/Settings/Users/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, CircularProgress, @@ -31,10 +45,6 @@ import UpdateUserDialog from "./dialog/UpdateUserDialog"; import { sortByName } from "../../../../services/utils"; import { isSearchMatching } from "../../../../utils/stringUtils"; -/** - * Types - */ - enum UserActionKind { ADD = "ADD", EDIT = "EDIT", @@ -48,10 +58,6 @@ interface UserAction extends Action { payload?: UserDetailsDTO["id"] | UserDetailsDTO | UserDetailsDTO[] | UserEdit; } -/** - * Utils - */ - const reducer = produce((draft, action) => { const { payload } = action; @@ -80,10 +86,6 @@ const reducer = produce((draft, action) => { } }); -/** - * Component - */ - function Users() { const [userToDelete, setUserToDelete] = useState(); const [userToEdit, setUserToEdit] = useState(); diff --git a/webapp/src/components/App/Settings/index.tsx b/webapp/src/components/App/Settings/index.tsx index 462a3ad428..e1479ed8b8 100644 --- a/webapp/src/components/App/Settings/index.tsx +++ b/webapp/src/components/App/Settings/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import SettingsIcon from "@mui/icons-material/Settings"; import { TabContext, TabList, TabPanel } from "@mui/lab"; import { Box, Tab } from "@mui/material"; @@ -15,10 +29,6 @@ import { } from "../../../redux/selectors"; import { tuple } from "../../../utils/tsUtils"; -/** - * Component - */ - function Settings() { const [tabValue, setTabValue] = useState("1"); const [t] = useTranslation(); diff --git a/webapp/src/components/App/Settings/utils.ts b/webapp/src/components/App/Settings/utils.ts index 73969f176c..b074304987 100644 --- a/webapp/src/components/App/Settings/utils.ts +++ b/webapp/src/components/App/Settings/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as RA from "ramda-adjunct"; import { RoleType } from "../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandImportButton.tsx b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandImportButton.tsx index 87127a3cec..3c0912d1f4 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandImportButton.tsx +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandImportButton.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useRef } from "react"; import { useTranslation } from "react-i18next"; import { useSnackbar } from "notistack"; diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/CommandMatrixViewer.tsx b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/CommandMatrixViewer.tsx index 3d65703877..d57efcec10 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/CommandMatrixViewer.tsx +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/CommandMatrixViewer.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button } from "@mui/material"; import { isString } from "ramda-adjunct"; import { useState } from "react"; diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/index.tsx b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/index.tsx index 0867cfbf4b..c53d7b7ef1 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/index.tsx +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + // @flow import { CSSProperties, useState } from "react"; import { DraggableProvided } from "react-beautiful-dnd"; diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/style.ts b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/style.ts index 55b979cdfc..e0d056e66c 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/style.ts +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListItem/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Accordion, Box, styled } from "@mui/material"; import DeleteIcon from "@mui/icons-material/HighlightOff"; import { PAPER_BACKGROUND_NO_TRANSPARENCY } from "../../../../../../../theme"; diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListView.tsx b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListView.tsx index a9b9d58168..5ba09ec873 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListView.tsx +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/DraggableCommands/CommandListView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { memo, useEffect, useRef } from "react"; import { FixedSizeList, areEqual, ListChildComponentProps } from "react-window"; import { diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/commandTypes.ts b/webapp/src/components/App/Singlestudy/Commands/Edition/commandTypes.ts index 89e368e793..76d63180d0 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/commandTypes.ts +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/commandTypes.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { CommandResultDTO } from "../../../../../common/types"; export interface CommandItem { diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/index.tsx b/webapp/src/components/App/Singlestudy/Commands/Edition/index.tsx index 15934c4ad2..cdb2098be6 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/index.tsx +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback, useEffect, useRef, useState } from "react"; import { useSnackbar } from "notistack"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/style.ts b/webapp/src/components/App/Singlestudy/Commands/Edition/style.ts index 6160ec5fca..50163125c0 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/style.ts +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, styled } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/Commands/Edition/utils.ts b/webapp/src/components/App/Singlestudy/Commands/Edition/utils.ts index 69df4c61f4..5d19407ad5 100644 --- a/webapp/src/components/App/Singlestudy/Commands/Edition/utils.ts +++ b/webapp/src/components/App/Singlestudy/Commands/Edition/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { CommandDTO, CommandResultDTO, diff --git a/webapp/src/components/App/Singlestudy/Commands/index.tsx b/webapp/src/components/App/Singlestudy/Commands/index.tsx index 858e60bd84..ef595a8eed 100644 --- a/webapp/src/components/App/Singlestudy/Commands/index.tsx +++ b/webapp/src/components/App/Singlestudy/Commands/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import Toolbar from "@mui/material/Toolbar"; import Divider from "@mui/material/Divider"; diff --git a/webapp/src/components/App/Singlestudy/Commands/style.ts b/webapp/src/components/App/Singlestudy/Commands/style.ts index 61cfb7f180..fab386d705 100644 --- a/webapp/src/components/App/Singlestudy/Commands/style.ts +++ b/webapp/src/components/App/Singlestudy/Commands/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Drawer, styled } from "@mui/material"; export const CommandDrawer = styled(Drawer)(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/CreateVariantDialog.tsx b/webapp/src/components/App/Singlestudy/HomeView/InformationView/CreateVariantDialog.tsx index 7c23b14a4f..06526db96e 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/CreateVariantDialog.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/CreateVariantDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useMemo, useState } from "react"; import { useNavigate } from "react-router"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/JobStepper.tsx b/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/JobStepper.tsx index 85f2edbf64..80ce0830c3 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/JobStepper.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/JobStepper.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import Stepper from "@mui/material/Stepper"; import Step from "@mui/material/Step"; import StepLabel from "@mui/material/StepLabel"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/index.tsx b/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/index.tsx index e5edcbad76..263a12d1a5 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/index.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Paper, styled, Typography } from "@mui/material"; import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/style.ts b/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/style.ts index 5b70ee2fca..296d4a5cb1 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/style.ts +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, StepConnector, diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/DetailsList.tsx b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/DetailsList.tsx index 55e6300dd7..295e521547 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/DetailsList.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/DetailsList.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemText from "@mui/material/ListItemText"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/index.tsx b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/index.tsx index 54e85cd6cf..7dae04424a 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/index.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { Editor, EditorState, getDefaultKeyBinding, RichUtils } from "draft-js"; import { Button } from "@mui/material"; @@ -140,8 +154,4 @@ function NoteEditorModal(props: Props) { ); } -NoteEditorModal.defaultProps = { - content: undefined, -}; - export default NoteEditorModal; diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/style.ts b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/style.ts index 2b6b2e9bb8..c5848881b5 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/style.ts +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/NodeEditorModal/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, styled, Typography } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/index.tsx b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/index.tsx index e49b5d2a15..9491982e92 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/index.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useSnackbar } from "notistack"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/utils.ts b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/utils.ts index 91ca0f7b57..4f2d146330 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/utils.ts +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/Notes/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable no-param-reassign */ import { ContentState, convertToRaw, EditorState } from "draft-js"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/InformationView/index.tsx b/webapp/src/components/App/Singlestudy/HomeView/InformationView/index.tsx index 590e271ac3..52b57f4935 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/InformationView/index.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/InformationView/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { Paper, Button, Box, Divider } from "@mui/material"; import { useNavigate } from "react-router-dom"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/index.tsx b/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/index.tsx index 284e53836e..3e483c8e21 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/index.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useMemo, useState } from "react"; import * as React from "react"; import { Box, styled } from "@mui/material"; diff --git a/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/treeconfig.ts b/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/treeconfig.ts index fd75119ad5..75fdc12ca7 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/treeconfig.ts +++ b/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/treeconfig.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + export const colors = ["#24CF9D", "#F3C918", "#E317DA", "#00B2FF"]; export const TILE_SIZE_X = 50; diff --git a/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/utils.ts b/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/utils.ts index cb53646e0a..f9225289fb 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/utils.ts +++ b/webapp/src/components/App/Singlestudy/HomeView/StudyTreeView/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable no-param-reassign */ import { GenericInfo, diff --git a/webapp/src/components/App/Singlestudy/HomeView/index.tsx b/webapp/src/components/App/Singlestudy/HomeView/index.tsx index 3f3c0806da..83f4d765a5 100644 --- a/webapp/src/components/App/Singlestudy/HomeView/index.tsx +++ b/webapp/src/components/App/Singlestudy/HomeView/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useNavigate } from "react-router-dom"; import { Box } from "@mui/material"; import Split from "react-split"; diff --git a/webapp/src/components/App/Singlestudy/NavHeader/Actions.tsx b/webapp/src/components/App/Singlestudy/NavHeader/Actions.tsx index b922b7589c..fb9dca2669 100644 --- a/webapp/src/components/App/Singlestudy/NavHeader/Actions.tsx +++ b/webapp/src/components/App/Singlestudy/NavHeader/Actions.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Tooltip, Typography, Chip, Button, Divider } from "@mui/material"; import HistoryOutlinedIcon from "@mui/icons-material/HistoryOutlined"; import ContentCopyIcon from "@mui/icons-material/ContentCopy"; diff --git a/webapp/src/components/App/Singlestudy/NavHeader/ActionsMenu.tsx b/webapp/src/components/App/Singlestudy/NavHeader/ActionsMenu.tsx index f72b73860c..7e0c7b9135 100644 --- a/webapp/src/components/App/Singlestudy/NavHeader/ActionsMenu.tsx +++ b/webapp/src/components/App/Singlestudy/NavHeader/ActionsMenu.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Menu, MenuItem, ListItemIcon, ListItemText } from "@mui/material"; import { SvgIconComponent } from "@mui/icons-material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/NavHeader/Details.tsx b/webapp/src/components/App/Singlestudy/NavHeader/Details.tsx index 3da34c1f23..2a59f1dca5 100644 --- a/webapp/src/components/App/Singlestudy/NavHeader/Details.tsx +++ b/webapp/src/components/App/Singlestudy/NavHeader/Details.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import ScheduleOutlinedIcon from "@mui/icons-material/ScheduleOutlined"; import UpdateOutlinedIcon from "@mui/icons-material/UpdateOutlined"; import AltRouteOutlinedIcon from "@mui/icons-material/AltRouteOutlined"; diff --git a/webapp/src/components/App/Singlestudy/NavHeader/index.tsx b/webapp/src/components/App/Singlestudy/NavHeader/index.tsx index 8518e8112e..decab0bfa8 100644 --- a/webapp/src/components/App/Singlestudy/NavHeader/index.tsx +++ b/webapp/src/components/App/Singlestudy/NavHeader/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState, MouseEvent } from "react"; import debug from "debug"; import { useSnackbar } from "notistack"; diff --git a/webapp/src/components/App/Singlestudy/PropertiesDialog.tsx b/webapp/src/components/App/Singlestudy/PropertiesDialog.tsx index 30b345ee28..c1600bf399 100644 --- a/webapp/src/components/App/Singlestudy/PropertiesDialog.tsx +++ b/webapp/src/components/App/Singlestudy/PropertiesDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import debug from "debug"; import * as R from "ramda"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/UpgradeDialog.tsx b/webapp/src/components/App/Singlestudy/UpgradeDialog.tsx index 7828d1b4c0..48663558b6 100644 --- a/webapp/src/components/App/Singlestudy/UpgradeDialog.tsx +++ b/webapp/src/components/App/Singlestudy/UpgradeDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import UpgradeIcon from "@mui/icons-material/Upgrade"; import { useMemo } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/Fields.tsx index d60eb0089f..8c6e2e411b 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import { useTranslation } from "react-i18next"; import { useOutletContext } from "react-router"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx index cdb28df743..8b8b178543 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { useTranslation } from "react-i18next"; import { StudyMetadata } from "../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/utils.ts index 4e869bba6c..3fb10e2782 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyMetadata } from "../../../../../../common/types"; import client from "../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/Fields.tsx index 8c2482b7f2..19a19d41a9 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import { useTranslation } from "react-i18next"; import NumberFE from "../../../../../common/fieldEditors/NumberFE"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/index.tsx index 0e8f90cd71..28e5ef9ee2 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../common/types"; import { updateStudySynthesis } from "../../../../../../redux/ducks/studySyntheses"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/utils.ts index 4a8b69e918..addfec700c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/AdvancedParameters/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DeepPartial } from "react-hook-form"; import { StudyMetadata } from "../../../../../../common/types"; import client from "../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/General/Fields.tsx index 3bd79f0c94..f4d23505b4 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, Divider } from "@mui/material"; import { useTranslation } from "react-i18next"; import SettingsIcon from "@mui/icons-material/Settings"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/Table.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/Table.tsx index 4abd82eb73..9b0648912a 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/Table.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/Table.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import TableForm from "../../../../../../../common/TableForm"; import { diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/index.tsx index e6499f591a..3f86bc643c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TabContext, TabList, TabListProps, TabPanel } from "@mui/lab"; import { Box, Button, Tab, Skeleton } from "@mui/material"; import { useState } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/utils.ts index d59661fe60..87e4f5a979 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AxiosResponse } from "axios"; import { StudyMetadata } from "../../../../../../../../common/types"; import client from "../../../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/withAreas.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/withAreas.tsx index 2862d14c13..05dfcb013f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/withAreas.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioBuilderDialog/withAreas.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ComponentType, useEffect, useMemo, useState } from "react"; import { Box } from "@mui/material"; import SplitView from "../../../../../../../common/SplitView"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/index.tsx index 6edda44cfb..80f78ef82c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, Divider } from "@mui/material"; import { useRef } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/utils.ts index d2098e2f4e..bd7c015df8 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ScenarioPlaylistDialog/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyMetadata } from "../../../../../../../../common/types"; import client from "../../../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/index.tsx index 182aad6bcc..19cbfdf8b9 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/index.tsx @@ -1,10 +1,24 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Accordion, AccordionDetails, AccordionSummary, Button, Divider, - Unstable_Grid2 as Grid, + Grid2 as Grid, } from "@mui/material"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import * as R from "ramda"; @@ -152,7 +166,7 @@ function ThematicTrimmingDialog(props: Props) { const fields = getFieldLabelsForGroup(api.getValues(), group) .filter(([, label]) => isSearchMatching(search, label)) .map(([name, label]) => ( - + )); @@ -172,12 +186,7 @@ function ThematicTrimmingDialog(props: Props) { )} - + {fields} diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/utils.ts index 61b29afa09..a3a16e5661 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/dialogs/ThematicTrimmingDialog/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; import { ThematicTrimmingConfig } from "../../../../../../../../services/api/studies/config/thematicTrimming/types"; import { O } from "ts-toolbelt"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/General/index.tsx index 312abef7d6..9d9ea519d9 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import * as R from "ramda"; import { useState } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/styles.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/General/styles.ts index db13197036..702ed0e462 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/styles.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/styles.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled } from "@mui/material"; export const FieldWithButton = styled("div")(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/General/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/General/utils.ts index 41a9c218cf..612e43080f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/General/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/General/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; import { StudyMetadata } from "../../../../../../common/types"; import client from "../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/Fields.tsx index 2686de44f9..143b3108ed 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import { useTranslation } from "react-i18next"; import { StudyMetadata } from "../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/index.tsx index 081f190175..775665d746 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../common/types"; import Form from "../../../../../common/Form"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/utils.ts index 7d0fbad5c9..319509ac63 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/Optimization/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; //////////////////////////////////////////////////////////////// diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/Fields.tsx index d62aeffbc3..d70ab020a4 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Table, TableBody, diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/index.tsx index 045296b256..2619fe284c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../common/types"; import Form from "../../../../../common/Form"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/utils.ts b/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/utils.ts index f962a46d86..19e42b5b33 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/TimeSeriesManagement/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DeepPartial } from "react-hook-form"; import { StudyMetadata } from "../../../../../../common/types"; import client from "../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx index 96bc285952..2cb4312daa 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; import { useMemo, useState } from "react"; import { useOutletContext } from "react-router"; diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx new file mode 100644 index 0000000000..88c1aaea1e --- /dev/null +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx @@ -0,0 +1,249 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { + Divider, + IconButton, + List, + ListItem, + ListItemButton, + ListItemIcon, + ListItemText, + ListSubheader, + Menu, + MenuItem, +} from "@mui/material"; +import FolderIcon from "@mui/icons-material/Folder"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; +import DeleteIcon from "@mui/icons-material/Delete"; +import { + getFileIcon, + getFileType, + type TreeFolder, + type DataCompProps, + isFolder, + canEditFile, +} from "../utils"; +import { Fragment, useState } from "react"; +import EmptyView from "../../../../../common/page/SimpleContent"; +import { useTranslation } from "react-i18next"; +import { Filename, Menubar } from "./styles"; +import UploadFileButton from "../../../../../common/buttons/UploadFileButton"; +import ConfirmationDialog from "../../../../../common/dialogs/ConfirmationDialog"; +import useConfirm from "../../../../../../hooks/useConfirm"; +import { deleteFile } from "../../../../../../services/api/studies/raw"; +import useEnqueueErrorSnackbar from "../../../../../../hooks/useEnqueueErrorSnackbar"; +import { toError } from "../../../../../../utils/fnUtils"; +import { useOutletContext } from "react-router"; +import type { StudyMetadata } from "../../../../../../common/types"; +import { useSnackbar } from "notistack"; + +function Folder(props: DataCompProps) { + const { + filename, + filePath, + treeData, + canEdit, + setSelectedFile, + reloadTreeData, + studyId, + } = props; + + const { t } = useTranslation(); + const { study } = useOutletContext<{ study: StudyMetadata }>(); + const replaceAction = useConfirm(); + const deleteAction = useConfirm(); + const { enqueueSnackbar } = useSnackbar(); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + + const [menuData, setMenuData] = useState(null); + + const treeFolder = treeData as TreeFolder; + const fileList = Object.entries(treeFolder); + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleValidateUpload = (file: File) => { + const childWithSameName = treeFolder[file.name]; + if (childWithSameName) { + if (isFolder(childWithSameName)) { + throw new Error(t("study.debug.folder.upload.error.replaceFolder")); + } + + return replaceAction.showConfirm(); + } + }; + + const handleMenuClose = () => { + setMenuData(null); + }; + + const handleDeleteClick = () => { + handleMenuClose(); + + if (!menuData) { + return; + } + + deleteAction.showConfirm().then((confirm) => { + if (confirm) { + deleteFile({ studyId, path: menuData.filePath }) + .then(() => { + enqueueSnackbar("wqed", { variant: "success" }); + reloadTreeData(); + }) + .catch((err) => { + enqueueErrorSnackbar("Delete failed", toError(err)); + }); + } + }); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + <> + + + {filename} + {canEdit && ( + `${filePath}/${file.name}`} + onUploadSuccessful={reloadTreeData} + validate={handleValidateUpload} + /> + )} + + + } + sx={{ + height: 1, + overflow: "auto", + // Prevent scroll to display + ...(fileList.length === 0 && { + display: "flex", + flexDirection: "column", + }), + }} + dense + > + {fileList.length > 0 ? ( + fileList.map(([filename, data], index, arr) => { + const path = `${filePath}/${filename}`; + const type = getFileType(data); + const Icon = getFileIcon(type); + const isNotLast = index !== arr.length - 1; + + return ( + + { + setMenuData({ + anchorEl: event.currentTarget, + filePath: path, + }); + }} + > + + + ) + } + disablePadding + > + + setSelectedFile({ + filename, + fileType: type, + filePath: path, + treeData: data, + }) + } + > + + + + + + + {isNotLast && } + + ); + }) + ) : ( + + )} + + {/* Items menu */} + + + + {t("global.delete")} + + + {/* Confirm file replacement */} + + {t("study.debug.folder.upload.replaceFileConfirm.message")} + + {/* Confirm file deletion */} + + {t("study.debug.file.deleteConfirm.message")} + + + ); +} + +export default Folder; diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Image.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Image.tsx new file mode 100644 index 0000000000..23aa34e993 --- /dev/null +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Image.tsx @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { useTranslation } from "react-i18next"; +import EmptyView from "../../../../../common/page/SimpleContent"; +import ImageIcon from "@mui/icons-material/Image"; +import { Filename, Flex, Menubar } from "./styles"; +import type { DataCompProps } from "../utils"; + +function Image({ filename }: DataCompProps) { + const { t } = useTranslation(); + + return ( + + + {filename} + + + + ); +} + +export default Image; diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx index 3923ce319a..1a8eb2fce5 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx @@ -1,63 +1,74 @@ -import { useState } from "react"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; -import { AxiosError } from "axios"; import { useSnackbar } from "notistack"; -import SaveIcon from "@mui/icons-material/Save"; -import { Box, Button, Typography } from "@mui/material"; -import { useUpdateEffect } from "react-use"; import { editStudy, getStudyData } from "../../../../../../services/api/study"; -import { Header, Root } from "./style"; -import JSONEditor from "../../../../../common/JSONEditor"; +import JSONEditor, { JSONEditorProps } from "../../../../../common/JSONEditor"; import usePromiseWithSnackbarError from "../../../../../../hooks/usePromiseWithSnackbarError"; import UsePromiseCond from "../../../../../common/utils/UsePromiseCond"; -import useEnqueueErrorSnackbar from "../../../../../../hooks/useEnqueueErrorSnackbar"; - -interface Props { - path: string; - studyId: string; -} +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"; -function Json({ path, studyId }: Props) { +function Json({ filePath, filename, studyId, canEdit }: DataCompProps) { const [t] = useTranslation(); const { enqueueSnackbar } = useSnackbar(); - const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); - const [jsonData, setJsonData] = useState(null); - const [isSaveAllowed, setIsSaveAllowed] = useState(false); + const [currentJson, setCurrentJson] = useState(); const res = usePromiseWithSnackbarError( - () => getStudyData(studyId, path, -1), + () => getStudyData(studyId, filePath, -1), { errorMessage: t("studies.error.retrieveData"), - deps: [studyId, path], + deps: [studyId, filePath], }, ); - // Reset save button when path changes - useUpdateEffect(() => { - setIsSaveAllowed(false); - }, [studyId, path]); + useEffect(() => { + setCurrentJson(res.data); + }, [res.data]); //////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////// - const handleSaveJson = async () => { - if (isSaveAllowed && jsonData) { - try { - await editStudy(jsonData, studyId, path); - enqueueSnackbar(t("studies.success.saveData"), { - variant: "success", - }); - setIsSaveAllowed(false); - } catch (e) { - enqueueErrorSnackbar(t("studies.error.saveData"), e as AxiosError); - } + const handleSave: JSONEditorProps["onSave"] = (json) => { + return editStudy(json, studyId, filePath); + }; + + const handleSaveSuccessful: JSONEditorProps["onSaveSuccessful"] = (json) => { + setCurrentJson(json); + + 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 handleJsonChange = (newJson: string) => { - setJsonData(newJson); - setIsSaveAllowed(true); + const handleUploadSuccessful = () => { + res.reload(); }; //////////////////////////////////////////////////////////////// @@ -65,38 +76,33 @@ function Json({ path, studyId }: Props) { //////////////////////////////////////////////////////////////// return ( - -
- -
- ( - - - - )} - /> -
+ ( + + + {filename} + {canEdit && ( + + )} + + + + + )} + /> ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx index c09b8c645f..4957e3a88e 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx @@ -1,25 +1,30 @@ -import { useOutletContext } from "react-router"; -import { MatrixStats, StudyMetadata } from "../../../../../../common/types"; -import { Root, Content } from "./style"; -import MatrixInput from "../../../../../common/MatrixInput"; - -interface Props { - path: string; -} +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ -function Matrix({ path }: Props) { - const { study } = useOutletContext<{ study: StudyMetadata }>(); - - //////////////////////////////////////////////////////////////// - // JSX - //////////////////////////////////////////////////////////////// +import { MatrixStats } from "../../../../../../common/types"; +import MatrixInput from "../../../../../common/MatrixInput"; +import type { DataCompProps } from "../utils"; +function Matrix({ studyId, filename, filePath, canEdit }: DataCompProps) { return ( - - - - - + ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx index 7f24d01f99..4cf121b951 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx @@ -1,36 +1,95 @@ -import { useState } from "react"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; -import { Button } from "@mui/material"; -import UploadOutlinedIcon from "@mui/icons-material/UploadOutlined"; -import { getStudyData, importFile } from "../../../../../../services/api/study"; -import { Content, Header, Root } from "./style"; -import ImportDialog from "../../../../../common/dialogs/ImportDialog"; +import { Box, useTheme } from "@mui/material"; +import { getStudyData } from "../../../../../../services/api/study"; import usePromiseWithSnackbarError from "../../../../../../hooks/usePromiseWithSnackbarError"; import UsePromiseCond from "../../../../../common/utils/UsePromiseCond"; -import { useDebugContext } from "../DebugContext"; +import { + Light as SyntaxHighlighter, + type SyntaxHighlighterProps, +} from "react-syntax-highlighter"; +import xml from "react-syntax-highlighter/dist/esm/languages/hljs/xml"; +import plaintext from "react-syntax-highlighter/dist/esm/languages/hljs/plaintext"; +import ini from "react-syntax-highlighter/dist/esm/languages/hljs/ini"; +import properties from "react-syntax-highlighter/dist/esm/languages/hljs/properties"; +import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs"; +import type { DataCompProps } from "../utils"; +import DownloadButton from "../../../../../common/buttons/DownloadButton"; +import { downloadFile } from "../../../../../../utils/fileUtils"; +import { Filename, Flex, Menubar } from "./styles"; +import UploadFileButton from "../../../../../common/buttons/UploadFileButton"; + +SyntaxHighlighter.registerLanguage("xml", xml); +SyntaxHighlighter.registerLanguage("plaintext", plaintext); +SyntaxHighlighter.registerLanguage("ini", ini); +SyntaxHighlighter.registerLanguage("properties", properties); + +// Ex: "[2024-05-21 17:18:57][solver][check]" +const logsRegex = /^(\[[^\]]*\]){3}/; +// Ex: "EXP : 0" +const propertiesRegex = /^[^:]+ : [^:]+/; + +function getSyntaxProps(data: string | string[]): SyntaxHighlighterProps { + const isArray = Array.isArray(data); + const text = isArray ? data.join("\n") : data; -interface Props { - studyId: string; - path: string; + return { + children: text, + showLineNumbers: isArray, + language: (() => { + const firstLine = text.split("\n")[0]; + if (firstLine.startsWith(" getStudyData(studyId, path), { - errorMessage: t("studies.error.retrieveData"), - deps: [studyId, path], - }); + const res = usePromiseWithSnackbarError( + () => getStudyData(studyId, filePath), + { + errorMessage: t("studies.error.retrieveData"), + deps: [studyId, filePath], + }, + ); //////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////// - const handleImport = async (file: File) => { - await importFile(file, studyId, path); - reloadTreeData(); + const handleDownload = () => { + if (res.data) { + downloadFile( + res.data, + filename.endsWith(".txt") ? filename : `${filename}.txt`, + ); + } + }; + + const handleUploadSuccessful = () => { + res.reload(); }; //////////////////////////////////////////////////////////////// @@ -38,34 +97,41 @@ function Text({ studyId, path }: Props) { //////////////////////////////////////////////////////////////// return ( - -
- -
- ( - - {data} - - )} - /> - {openImportDialog && ( - setOpenImportDialog(false)} - onImport={handleImport} - /> + ( + + + {filename} + {canEdit && ( + + )} + + + + + + )} -
+ /> ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx index 0cb75a3eab..f387b7ef9c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx @@ -1,24 +1,60 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import Text from "./Text"; +import Image from "./Image"; import Json from "./Json"; import Matrix from "./Matrix"; -import { FileType } from "../utils"; +import Folder from "./Folder"; +import { canEditFile, type FileInfo, type FileType } from "../utils"; +import type { DataCompProps } from "../utils"; +import ViewWrapper from "../../../../../common/page/ViewWrapper"; +import type { StudyMetadata } from "../../../../../../common/types"; -interface Props { - studyId: string; - fileType: FileType; - filePath: string; +interface Props extends FileInfo { + study: StudyMetadata; + setSelectedFile: (file: FileInfo) => void; + reloadTreeData: () => void; } -const componentByFileType = { +type DataComponent = React.ComponentType; + +const componentByFileType: Record = { matrix: Matrix, json: Json, - file: Text, + text: Text, + image: Image, + folder: Folder, } as const; -function Data({ studyId, fileType, filePath }: Props) { +function Data(props: Props) { + const { study, setSelectedFile, reloadTreeData, ...fileInfo } = props; + const { fileType, filePath } = fileInfo; + const canEdit = canEditFile(study, filePath); const DataViewer = componentByFileType[fileType]; - return ; + return ( + + + + ); } export default Data; diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/style.ts b/webapp/src/components/App/Singlestudy/explore/Debug/Data/style.ts deleted file mode 100644 index b0143fdec8..0000000000 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/style.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { styled, Box, Paper } from "@mui/material"; - -export const Root = styled(Box)(({ theme }) => ({ - flex: 1, - height: "100%", - width: "100%", - display: "flex", - flexFlow: "column nowrap", - justifyContent: "flex-start", - alignItems: "center", - padding: theme.spacing(1, 1), -})); - -export const Header = styled(Box)(({ theme }) => ({ - width: "100%", - display: "flex", - flexFlow: "row nowrap", - justifyContent: "space-between", - alignItems: "center", - marginBottom: theme.spacing(1), -})); - -export const Content = styled(Paper)(({ theme }) => ({ - padding: theme.spacing(2), - boxSizing: "border-box", - flex: 1, - width: "100%", - display: "flex", - flexFlow: "column nowrap", - justifyContent: "flex-start", - alignItems: "flex-start", - overflow: "auto", - position: "relative", -})); diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/styles.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/styles.tsx new file mode 100644 index 0000000000..3800cd6bb0 --- /dev/null +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/styles.tsx @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { styled } from "@mui/material"; + +export const Flex = styled("div")(({ theme }) => ({ + height: "100%", + display: "flex", + flexDirection: "column", + gap: theme.spacing(1), +})); + +export const Menubar = styled("div")(({ theme }) => ({ + display: "flex", + justifyContent: "flex-end", + alignItems: "center", + gap: theme.spacing(1), +})); + +export const Filename = styled((props: { children?: string }) => ( +
+))({ + flex: 1, + overflow: "hidden", + textOverflow: "ellipsis", +}); diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/DebugContext.ts b/webapp/src/components/App/Singlestudy/explore/Debug/DebugContext.ts index c602e0e98f..4e10130ef9 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/DebugContext.ts +++ b/webapp/src/components/App/Singlestudy/explore/Debug/DebugContext.ts @@ -1,15 +1,26 @@ -import { createContext, useContext } from "react"; -import type { File } from "./utils"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { createContext } from "react"; +import type { FileInfo } from "./utils"; import { voidFn } from "../../../../../utils/fnUtils"; const initialDebugContextValue = { - onFileSelect: voidFn<[File]>, + setSelectedFile: voidFn<[FileInfo]>, reloadTreeData: voidFn, }; const DebugContext = createContext(initialDebugContextValue); -export const useDebugContext = (): typeof initialDebugContextValue => - useContext(DebugContext); - export default DebugContext; diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Tree/FileTreeItem.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Tree/FileTreeItem.tsx index b9e40f6a3d..dbc52c5a9f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Tree/FileTreeItem.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Tree/FileTreeItem.tsx @@ -1,29 +1,41 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; -import { TreeItem } from "@mui/x-tree-view"; -import { TreeData, determineFileType, getFileIcon } from "../utils"; -import { useDebugContext } from "../DebugContext"; +import { TreeData, getFileType, getFileIcon, isFolder } from "../utils"; +import DebugContext from "../DebugContext"; +import { useContext } from "react"; +import TreeItemEnhanced from "../../../../../common/TreeItemEnhanced"; interface Props { name: string; - content: TreeData; path: string; + treeData: TreeData; } -function FileTreeItem({ name, content, path }: Props) { - const { onFileSelect } = useDebugContext(); - const filePath = `${path}/${name}`; - const fileType = determineFileType(content); +function FileTreeItem({ name, treeData, path }: Props) { + const { setSelectedFile } = useContext(DebugContext); + const filePath = path ? `${path}/${name}` : name; + const fileType = getFileType(treeData); const FileIcon = getFileIcon(fileType); - const isFolderEmpty = !Object.keys(content).length; //////////////////////////////////////////////////////////////// // Event handlers //////////////////////////////////////////////////////////////// const handleClick = () => { - if (fileType !== "folder") { - onFileSelect({ fileType, filePath }); - } + setSelectedFile({ fileType, filename: name, filePath, treeData }); }; //////////////////////////////////////////////////////////////// @@ -31,33 +43,26 @@ function FileTreeItem({ name, content, path }: Props) { //////////////////////////////////////////////////////////////// return ( - - - {name} + + + {name} } + onClick={handleClick} > - {typeof content === "object" && - Object.keys(content).map((childName) => ( + {isFolder(treeData) && + Object.keys(treeData).map((childName) => ( ))} - + ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Tree/index.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Tree/index.tsx index 577f388efb..417ef33b4f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Tree/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Tree/index.tsx @@ -1,25 +1,72 @@ -import { TreeView } from "@mui/x-tree-view"; -import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import ChevronRightIcon from "@mui/icons-material/ChevronRight"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { SimpleTreeView } from "@mui/x-tree-view/SimpleTreeView"; import FileTreeItem from "./FileTreeItem"; -import { TreeData } from "../utils"; +import type { TreeFolder } from "../utils"; +import { getParentPaths } from "../../../../../../utils/pathUtils"; interface Props { - data: TreeData; + data: TreeFolder; + // `currentPath` must not be `undefined` to make `SimpleTreeView` controlled + currentPath: string | null; + expandedItems: string[]; + setExpandedItems: React.Dispatch>; } -function Tree({ data }: Props) { +function Tree(props: Props) { + const { data, currentPath, expandedItems, setExpandedItems } = props; + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleExpandedItemsChange = ( + event: React.SyntheticEvent, + itemIds: string[], + ) => { + setExpandedItems(itemIds); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + // `SimpleTreeView` must be controlled because selected item can be changed manually + // by `Folder` component, or by the `path` URL parameter at view mount. + // The use of `selectedItems` and `expandedItems` make the component controlled. + return ( - } - defaultExpandIcon={} + - {typeof data === "object" && - Object.keys(data).map((key) => ( - - ))} - + {Object.keys(data).map((filename) => ( + + ))} + ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/index.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/index.tsx index 1f6ae3cc2d..96f8de8e91 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/index.tsx @@ -1,6 +1,20 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useOutletContext } from "react-router-dom"; +import { useOutletContext, useSearchParams } from "react-router-dom"; import { Box } from "@mui/material"; import Tree from "./Tree"; import Data from "./Data"; @@ -9,17 +23,29 @@ import UsePromiseCond from "../../../../common/utils/UsePromiseCond"; import usePromiseWithSnackbarError from "../../../../../hooks/usePromiseWithSnackbarError"; import { getStudyData } from "../../../../../services/api/study"; import DebugContext from "./DebugContext"; -import { TreeData, filterTreeData, File } from "./utils"; +import { + getFileType, + type TreeData, + type FileInfo, + type TreeFolder, +} from "./utils"; +import * as R from "ramda"; +import SplitView from "../../../../common/SplitView"; +import { useUpdateEffect } from "react-use"; function Debug() { const [t] = useTranslation(); const { study } = useOutletContext<{ study: StudyMetadata }>(); - const [selectedFile, setSelectedFile] = useState(); + const [selectedFile, setSelectedFile] = useState(null); + // Allow to keep expanded items when the tree is reloaded with `reloadTreeData` + const [expandedItems, setExpandedItems] = useState([]); + const [searchParams, setSearchParams] = useSearchParams(); + const pathInUrl = searchParams.get("path"); const res = usePromiseWithSnackbarError( async () => { - const treeData = await getStudyData(study.id, "", -1); - return filterTreeData(treeData); + const treeData = await getStudyData(study.id, "", -1); + return R.omit(["Desktop", "study", "logs"], treeData); }, { errorMessage: t("studies.error.retrieveData"), @@ -29,43 +55,89 @@ function Debug() { const contextValue = useMemo( () => ({ - onFileSelect: setSelectedFile, + setSelectedFile, reloadTreeData: res.reload, }), [res.reload], ); + useUpdateEffect(() => { + const firstChildName = Object.keys(res.data ?? {})[0]; + const firstChildTreeData = R.path([firstChildName], res.data); + + const pathInUrlParts = pathInUrl?.split("/"); + const urlPathTreeData = pathInUrlParts + ? R.path(pathInUrlParts, res.data) + : null; + + let fileInfo: FileInfo | null = null; + + if (urlPathTreeData) { + fileInfo = { + fileType: getFileType(urlPathTreeData), + treeData: urlPathTreeData, + filename: R.last(pathInUrlParts!)!, + filePath: pathInUrl!, + }; + } else if (firstChildTreeData) { + fileInfo = { + fileType: getFileType(firstChildTreeData), + treeData: firstChildTreeData, + filename: firstChildName, + filePath: firstChildName, + }; + } + + if (fileInfo) { + setSelectedFile(fileInfo); + } else { + setSelectedFile(null); + } + }, [res.data, pathInUrl]); + + useUpdateEffect(() => { + if (selectedFile?.filePath !== pathInUrl) { + setSearchParams({ path: selectedFile?.filePath || "" }); + } + }, [selectedFile?.filePath]); + + // TODO: to remove after ANT-2217 solved + useUpdateEffect(() => { + contextValue.reloadTreeData(); + }, [study.archived]); + //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// return ( - - + + ( - <> - - - - - {selectedFile && } - - + + + )} /> - + + {selectedFile && ( + + )} + + ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts b/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts index a6e3798806..b1d8653f07 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts @@ -1,52 +1,88 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import DataObjectIcon from "@mui/icons-material/DataObject"; import TextSnippetIcon from "@mui/icons-material/TextSnippet"; +import ImageIcon from "@mui/icons-material/Image"; import FolderIcon from "@mui/icons-material/Folder"; import DatasetIcon from "@mui/icons-material/Dataset"; import { SvgIconComponent } from "@mui/icons-material"; +import * as RA from "ramda-adjunct"; +import type { StudyMetadata } from "../../../../../common/types"; //////////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////////// -export type FileType = "json" | "file" | "matrix"; +export type TreeFile = string | string[]; + +export interface TreeFolder { + [key: string]: TreeFile | TreeFolder; +} + +export type TreeData = TreeFolder | TreeFile; + +export type FileType = "json" | "matrix" | "text" | "image" | "folder"; -export interface File { +export interface FileInfo { fileType: FileType; + filename: string; filePath: string; + treeData: TreeData; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type TreeData = Record | string; +export interface DataCompProps extends FileInfo { + studyId: string; + canEdit: boolean; + setSelectedFile: (file: FileInfo) => void; + reloadTreeData: () => void; +} //////////////////////////////////////////////////////////////// -// Utils +// File Info //////////////////////////////////////////////////////////////// -//Maps file types and folder to their corresponding icon components. -const iconByFileType: Record = { +// Maps file types to their corresponding icon components. +const iconByFileType: Record = { matrix: DatasetIcon, json: DataObjectIcon, + text: TextSnippetIcon, + image: ImageIcon, folder: FolderIcon, - file: TextSnippetIcon, } as const; /** - * Gets the icon component for a given file type or folder. + * Gets the icon component for a given file type. * - * @param type - The type of the file or "folder". + * @param type - The type of the file. * @returns The corresponding icon component. */ -export const getFileIcon = (type: FileType | "folder"): SvgIconComponent => { - return iconByFileType[type] || TextSnippetIcon; -}; +export function getFileIcon(type: FileType): SvgIconComponent { + return iconByFileType[type]; +} + +export function isFolder(treeData: TreeData): treeData is TreeFolder { + return RA.isPlainObj(treeData); +} /** - * Determines the file type based on the tree data. + * Gets the file type based on the tree data. * * @param treeData - The data of the tree item. - * @returns The determined file type or "folder". + * @returns The corresponding file type. */ -export const determineFileType = (treeData: TreeData): FileType | "folder" => { +export function getFileType(treeData: TreeData): FileType { if (typeof treeData === "string") { if ( treeData.startsWith("matrix://") || @@ -57,20 +93,29 @@ export const determineFileType = (treeData: TreeData): FileType | "folder" => { if (treeData.startsWith("json://") || treeData.endsWith(".json")) { return "json"; } + if (treeData.startsWith("file://") && treeData.endsWith(".ico")) { + return "image"; + } } - return typeof treeData === "object" ? "folder" : "file"; -}; + return isFolder(treeData) ? "folder" : "text"; +} + +//////////////////////////////////////////////////////////////// +// Rights +//////////////////////////////////////////////////////////////// /** - * Filters out specific keys from the tree data. + * Checks if a study's file can be edited. * - * @param data - The original tree data. - * @returns The filtered tree data. + * @param study - The study where the file is located. + * @param filePath - The path of the file. + * @returns True if the file can be edited, false otherwise. */ -export const filterTreeData = (data: TreeData): TreeData => { - const excludedKeys = new Set(["Desktop", "study", "logs"]); - - return Object.fromEntries( - Object.entries(data).filter(([key]) => !excludedKeys.has(key)), +export function canEditFile(study: StudyMetadata, filePath: string): boolean { + return ( + !study.archived && + (filePath === "user" || filePath.startsWith("user/")) && + // To remove when Xpansion tool configuration will be moved to "input/expansion" directory + !(filePath === "user/expansion" || filePath.startsWith("user/expansion/")) ); -}; +} diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreaPropsView.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreaPropsView.tsx index 0976bf3e36..feb39df236 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreaPropsView.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreaPropsView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { Area } from "../../../../../../common/types"; import PropertiesView from "../../../../../common/PropertiesView"; @@ -56,8 +70,4 @@ function AreaPropsView(props: PropsType) { ); } -AreaPropsView.defaultProps = { - currentArea: undefined, -}; - export default AreaPropsView; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreasTab.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreasTab.tsx index 0bc26081dc..508e75705a 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreasTab.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/AreasTab.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useMemo } from "react"; import { useLocation, useNavigate, useOutletContext } from "react-router-dom"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/AllocationField.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/AllocationField.tsx index 40b99c009a..f8cb147368 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/AllocationField.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/AllocationField.tsx @@ -1,9 +1,23 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Typography, Grid } from "@mui/material"; -import { t } from "i18next"; import { FieldArrayWithId } from "react-hook-form"; import NumberFE from "../../../../../../../common/fieldEditors/NumberFE"; import { useFormContextPlus } from "../../../../../../../common/Form"; import { AllocationFormFields } from "./utils"; +import { validateNumber } from "../../../../../../../../utils/validationUtils"; interface Props { field: FieldArrayWithId; @@ -34,15 +48,10 @@ function AllocationField({ field, index, label }: Props) { diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/Fields.tsx index e6ed81c9f6..ce708a4771 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useFieldArray } from "react-hook-form"; import { useOutletContext } from "react-router"; import { useFormContextPlus } from "../../../../../../../common/Form"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/index.tsx index 4e12df8757..8231ad0613 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Grid } from "@mui/material"; import { useOutletContext } from "react-router"; import { useState } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/utils.ts index 5544255e52..46041fdcc2 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Allocation/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyMetadata, Area, diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/CorrelationField.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/CorrelationField.tsx index 98be0f2d7c..b1cdec1ac0 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/CorrelationField.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/CorrelationField.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Typography, Grid } from "@mui/material"; import { FieldArrayWithId } from "react-hook-form"; import { useTranslation } from "react-i18next"; @@ -6,6 +20,7 @@ import { CorrelationFormFields } from "./utils"; import { useFormContextPlus } from "../../../../../../../common/Form"; import useAppSelector from "../../../../../../../../redux/hooks/useAppSelector"; import { getCurrentArea } from "../../../../../../../../redux/selectors"; +import { validateNumber } from "../../../../../../../../utils/validationUtils"; interface Props { field: FieldArrayWithId; @@ -40,19 +55,10 @@ function CorrelationField({ field, index, label }: Props) { diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/Fields.tsx index 6a45074fd7..60a99464c7 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useFieldArray } from "react-hook-form"; import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/index.tsx index 631398ff0a..d6dce25747 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Grid } from "@mui/material"; import { useOutletContext } from "react-router"; import { useState } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/utils.ts index bd5e574389..dc2b547e63 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/Correlation/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyMetadata, Area, diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx index 2a8796074c..ff6218de35 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../common/types"; import useAppSelector from "../../../../../../../redux/hooks/useAppSelector"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrixDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrixDialog.tsx index 3a2a1fefd6..85223c55db 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrixDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrixDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Button, Box } from "@mui/material"; import { useTranslation } from "react-i18next"; import BasicDialog, { diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/index.tsx index 79bef831a5..d63487a116 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../../common/types"; import useAppSelector from "../../../../../../../../redux/hooks/useAppSelector"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/utils.ts index e8fdc21be5..0c0525059a 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/InflowStructure/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { type StudyMetadata } from "../../../../../../../../common/types"; import client from "../../../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/Fields.tsx index fb8869a760..91d3cdb6ee 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import NumberFE from "../../../../../../../common/fieldEditors/NumberFE"; import SelectFE from "../../../../../../../common/fieldEditors/SelectFE"; import SwitchFE from "../../../../../../../common/fieldEditors/SwitchFE"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/index.tsx index 1c1cd56489..6b778d69da 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../../common/types"; import useAppSelector from "../../../../../../../../redux/hooks/useAppSelector"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/utils.ts index 1616fb3e92..ebb3a34512 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ManagementOptions/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Area, StudyMetadata } from "../../../../../../../../common/types"; import client from "../../../../../../../../services/api/client"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/SplitHydroMatrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/SplitHydroMatrix.tsx index 6d64a3f378..1adbc4e2b9 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/SplitHydroMatrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/SplitHydroMatrix.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import SplitView, { SplitViewProps } from "../../../../../../common/SplitView"; import HydroMatrix from "./HydroMatrix"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ViewMatrixButton.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ViewMatrixButton.tsx index 89e5bb7c14..e049eec4c2 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ViewMatrixButton.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/ViewMatrixButton.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Button } from "@mui/material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/hooks/useAreasOptions.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/hooks/useAreasOptions.ts index 4678358d00..611c671625 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/hooks/useAreasOptions.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/hooks/useAreasOptions.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo } from "react"; import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx index cca7f9519a..4209e439bf 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo } from "react"; import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/style.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/style.ts index 84ff8c71fe..b707cafec5 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/style.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled, Box, Paper } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts index 7b4878aa73..316745826e 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { MatrixStats, MatrixType } from "../../../../../../../common/types"; import { SplitViewProps } from "../../../../../../common/SplitView"; import { getAllocationMatrix } from "./Allocation/utils"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Load.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Load.tsx index 030a09e0ee..a9d67519de 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Load.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Load.tsx @@ -1,12 +1,22 @@ -import { useOutletContext } from "react-router"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import useAppSelector from "../../../../../../redux/hooks/useAppSelector"; import { getCurrentAreaId } from "../../../../../../redux/selectors"; -import { MatrixStats, StudyMetadata } from "../../../../../../common/types"; -import MatrixInput from "../../../../../common/MatrixInput"; -import { Root } from "./style"; +import Matrix from "../../../../../common/MatrixGrid/Matrix"; function Load() { - const { study } = useOutletContext<{ study: StudyMetadata }>(); const currentArea = useAppSelector(getCurrentAreaId); const url = `input/load/series/load_${currentArea}`; @@ -14,11 +24,7 @@ function Load() { // JSX //////////////////////////////////////////////////////////////// - return ( - - - - ); + return ; } export default Load; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/MiscGen.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/MiscGen.tsx index f1c41d6344..46451653a9 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/MiscGen.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/MiscGen.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import useAppSelector from "../../../../../../redux/hooks/useAppSelector"; import { getCurrentAreaId } from "../../../../../../redux/selectors"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx index 01a98538be..7055f2e792 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useOutletContext } from "react-router"; import { useMemo } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/index.tsx index 3efe409b9e..d654ba80c7 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Paper } from "@mui/material"; import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/utils.ts index 1abe75682a..5eef82d3f7 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + //////////////////////////////////////////////////////////////// // Enums //////////////////////////////////////////////////////////////// diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Fields.tsx index 7b7ea9774c..0ee371d7fa 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import NumberFE from "../../../../../../common/fieldEditors/NumberFE"; import SelectFE from "../../../../../../common/fieldEditors/SelectFE"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Form.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Form.tsx index fe39be2fc8..0d3b21cf17 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Form.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Form.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback } from "react"; import { Box, Button } from "@mui/material"; import { useParams, useOutletContext, useNavigate } from "react-router-dom"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Matrix.tsx index 0a3e269c85..4de557f4e5 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Matrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/Matrix.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as React from "react"; import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/index.tsx index 97637987d3..873774c391 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo, useState } from "react"; import { createMRTColumnHelper } from "material-react-table"; import { Box } from "@mui/material"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/utils.ts index 0c0418d8d3..f3e2520aa2 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Renewables/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Area, Cluster, diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Reserve.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Reserve.tsx index 1e45906346..0aae3af44d 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Reserve.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Reserve.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import useAppSelector from "../../../../../../redux/hooks/useAppSelector"; import { getCurrentAreaId } from "../../../../../../redux/selectors"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Solar.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Solar.tsx index 5e03558b39..2aeddedd2d 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Solar.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Solar.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import useAppSelector from "../../../../../../redux/hooks/useAppSelector"; import { getCurrentAreaId } from "../../../../../../redux/selectors"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Fields.tsx index 13af55156e..c492d318de 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { Box, Tooltip } from "@mui/material"; import NumberFE from "../../../../../../common/fieldEditors/NumberFE"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Form.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Form.tsx index 38a4bb2bc2..daa773bf9d 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Form.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Form.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback } from "react"; import { Box, Button } from "@mui/material"; import { useParams, useOutletContext, useNavigate } from "react-router-dom"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Matrix.tsx index 63ff535498..4fb27fdb55 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Matrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/Matrix.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as React from "react"; import * as R from "ramda"; import Tabs from "@mui/material/Tabs"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/index.tsx index 6c19931d74..9ffc3c4b27 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { createMRTColumnHelper } from "material-react-table"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/utils.ts index 04864fdc97..83bd3c60f7 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Storages/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyMetadata, Area } from "../../../../../../../common/types"; import client from "../../../../../../../services/api/client"; import type { PartialExceptFor } from "../../../../../../../utils/tsUtils"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx index 7f026c3c72..c8c15c8780 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Form.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Form.tsx index e37f4749dd..a549ff650f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Form.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Form.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback } from "react"; import { Box, Button } from "@mui/material"; import { useParams, useOutletContext, useNavigate } from "react-router-dom"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Matrix.tsx index 7b703cc3f5..e735f20402 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Matrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Matrix.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo, useState } from "react"; import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/index.tsx index 3a7cfd6801..1b71f18651 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo, useState } from "react"; import { createMRTColumnHelper } from "material-react-table"; import { Box } from "@mui/material"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/utils.ts index b5b0526ded..3a5895c8f6 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Area, Cluster, diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Wind.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Wind.tsx index 61298c83ce..39339779c4 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Wind.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Wind.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import useAppSelector from "../../../../../../redux/hooks/useAppSelector"; import { getCurrentAreaId } from "../../../../../../redux/selectors"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/common/clustersUtils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/common/clustersUtils.ts index 3d5c80dd30..56d94c7497 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/common/clustersUtils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/common/clustersUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { MRT_AggregationFn } from "material-react-table"; import { ThermalClusterWithCapacity } from "../Thermal/utils"; import { RenewableClusterWithCapacity } from "../Renewables/utils"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/index.tsx index be71efeb87..11536b3276 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../common/types"; import EmptyView from "../../../../../common/page/SimpleContent"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/style.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/style.ts index ba2de46bd6..73594af06e 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/style.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled, Box } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx index 6891123b8c..ca5540e438 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo } from "react"; import { Box } from "@mui/material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstPropsView.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstPropsView.tsx index 86269f33c6..e750c0a1aa 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstPropsView.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstPropsView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useMemo, useState } from "react"; import PropertiesView from "../../../../../common/PropertiesView"; import ListElement from "../../common/ListElement"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx index ec6c8bc91b..63a33457a3 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { useFormContext } from "react-hook-form"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx index 4290b3e599..f70facc13a 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { Box, Button, Typography } from "@mui/material"; import AddCircleOutlineRoundedIcon from "@mui/icons-material/AddCircleOutlineRounded"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx index f6a5d6ed59..2326e00edc 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AxiosError } from "axios"; import { useTranslation } from "react-i18next"; import { useSnackbar } from "notistack"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx index a28a2644fc..d821dfe10d 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AxiosError } from "axios"; import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx index 7677a78c4f..6eca935f4c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { BindingConstraint, OPERATORS, diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx index 3927abadbd..f6777e5f66 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { AllClustersAndLinks } from "../../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx index 48b2886008..04bb4e22b9 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ChangeEvent, useMemo, useState } from "react"; import { Box, Button, TextField, Typography } from "@mui/material"; import AddCircleOutlineRoundedIcon from "@mui/icons-material/AddCircleOutlineRounded"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx index ba9776cd1b..a3fd0f5cac 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { MatrixStats, StudyMetadata } from "../../../../../../../common/types"; import MatrixInput from "../../../../../../common/MatrixInput"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx index 02b104c14f..757c2eb019 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { FormControlLabel, Switch, Typography } from "@mui/material"; import { ReactNode } from "react"; import { ConstraintElementData, ConstraintElementRoot } from "./style"; @@ -11,11 +25,11 @@ interface ElementProps { onToggleType?: () => void; } -export default function ConstraintElement({ +function ConstraintElement({ isLink, left, right, - operator, + operator = "x", onToggleType, }: ElementProps) { const { t } = useTranslation(); @@ -39,6 +53,4 @@ export default function ConstraintElement({ ); } -ConstraintElement.defaultProps = { - operator: "x", -}; +export default ConstraintElement; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx index c2e7715f7b..f63a7288c1 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import HighlightOffIcon from "@mui/icons-material/HighlightOff"; import { Box } from "@mui/material"; import { PropsWithChildren } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/style.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/style.ts index f413ceb412..46d9d65f72 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/style.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Paper, styled } from "@mui/material"; export const ConstraintElementRoot = styled(Paper)(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx index 43dd656e8a..8b55779179 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { BindingConstraint } from "./utils"; import { Box, Button, Paper, Skeleton } from "@mui/material"; import Form from "../../../../../../common/Form"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts index 2c6bcdb00d..30b7dbc06e 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + //////////////////////////////////////////////////////////////// // Constants //////////////////////////////////////////////////////////////// diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx index f4348d786c..f272e92f75 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkPropsView.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkPropsView.tsx index 8ae6564e26..610dff4c74 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkPropsView.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkPropsView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import PropertiesView from "../../../../../common/PropertiesView"; import useAppSelector from "../../../../../../redux/hooks/useAppSelector"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkForm.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkForm.tsx index 039c2d8478..6bae8f2f63 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkForm.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkForm.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import { AxiosError } from "axios"; import { useMemo } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkMatrixView.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkMatrixView.tsx index 2a2a792b47..7cb84b4ae6 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkMatrixView.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/LinkMatrixView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as React from "react"; import { Divider, styled } from "@mui/material"; import Tabs from "@mui/material/Tabs"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/index.tsx index b2cf965232..bc2090ccff 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { LinkElement, StudyMetadata } from "../../../../../../../common/types"; import usePromise from "../../../../../../../hooks/usePromise"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/utils.ts index 19d6bcd4fc..d2cc46d077 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/LinkView/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { FieldValues } from "react-hook-form"; import { getStudyData } from "../../../../../../../services/api/study"; import { FilteringType } from "../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/index.tsx index fdc2a487c9..7d805ee3ba 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Links/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Links/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../common/types"; import EmptyView from "../../../../../common/page/SimpleContent"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaConfig.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaConfig.tsx index 9faac8b9ac..db30224399 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaConfig.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaConfig.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { ColorResult, MaterialPicker } from "react-color"; import { Box, TextField, Divider } from "@mui/material"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLink.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLink.tsx index 884ea1b280..87f38baf9f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLink.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLink.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { LinkElement } from "../../../../../../../common/types"; import { diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLinks.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLinks.tsx index 62ffb760a8..8f4f5dba3f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLinks.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/AreaLinks.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useOutletContext } from "react-router-dom"; import { StudyMetadata } from "../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/DeleteAreaDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/DeleteAreaDialog.tsx index 40d37b520f..fd7f4350ad 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/DeleteAreaDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/DeleteAreaDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, Typography } from "@mui/material"; import { AxiosError } from "axios"; import { useState } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/index.tsx index a605bd9247..b92d5a2c96 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { useOutletContext } from "react-router-dom"; import { StudyMetadata, UpdateAreaUi } from "../../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/style.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/style.ts index 58b439392b..aabe4c4bf2 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/style.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Areas/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled, Box } from "@mui/material"; import { HuePicker } from "react-color"; import DeleteIcon from "@mui/icons-material/Delete"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/CreateAreaDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/CreateAreaDialog.tsx index 0233fd313c..3acf5026ea 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/CreateAreaDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/CreateAreaDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import AddCircleIcon from "@mui/icons-material/AddCircle"; import FormDialog from "../../../../../common/dialogs/FormDialog"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/CreateDistrictDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/CreateDistrictDialog.tsx index f8b4191ac2..133f17c19e 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/CreateDistrictDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/CreateDistrictDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import AddCircleIcon from "@mui/icons-material/AddCircle"; import { useOutletContext } from "react-router"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/UpdateDistrictDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/UpdateDistrictDialog.tsx index d99e37fc91..b930986b51 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/UpdateDistrictDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/UpdateDistrictDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useOutletContext } from "react-router"; import { Delete, Edit } from "@mui/icons-material"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/index.tsx index 901f6f3dec..dae45e1dda 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Districts/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button } from "@mui/material"; import { useMemo, useState } from "react"; import { useOutletContext } from "react-router"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/CreateLayerDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/CreateLayerDialog.tsx index 46c01c2b45..90b4ee39a1 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/CreateLayerDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/CreateLayerDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import AddCircleIcon from "@mui/icons-material/AddCircle"; import { useOutletContext } from "react-router"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/UpdateLayerDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/UpdateLayerDialog.tsx index aa1c97b4eb..643e74cb33 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/UpdateLayerDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/UpdateLayerDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useOutletContext } from "react-router"; import { Delete, Edit } from "@mui/icons-material"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/index.tsx index 84ad34f15c..aff05df5c4 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/Layers/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button } from "@mui/material"; import { useMemo, useState } from "react"; import { useOutletContext } from "react-router"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/index.tsx index 9e3a23f083..e52842abc5 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapConfig/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, Tab } from "@mui/material"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapControlButtons.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapControlButtons.tsx index da11175123..973245da0f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapControlButtons.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapControlButtons.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import Button from "@mui/material/Button"; import ButtonGroup from "@mui/material/ButtonGroup"; import SettingsIcon from "@mui/icons-material/Settings"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapGraph.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapGraph.tsx index 7991a612f6..d416128028 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapGraph.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapGraph.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AxiosError } from "axios"; import { DebouncedFunc } from "lodash"; import { RefObject, useEffect, useState } from "react"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapHeader.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapHeader.tsx index 8824b7a3f1..e0d965f0cd 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapHeader.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/MapHeader.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Chip, Typography } from "@mui/material"; import { useTranslation } from "react-i18next"; import { LinkProperties } from "../../../../../../common/types"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Node.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Node.tsx index cd2775308a..2b55de00c4 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Node.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/Node.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import AddLinkIcon from "@mui/icons-material/AddLink"; import { StudyMapNode } from "../../../../../../redux/ducks/studyMaps"; import { NodeContainer, NodeDefault, NodeHighlighted } from "./style"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/index.tsx index ac02d2ded0..462d80aac6 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useMemo, useRef, useState } from "react"; import { useOutletContext } from "react-router-dom"; import AutoSizer from "react-virtualized-auto-sizer"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/style.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/style.ts index ca4a986c01..e3ebde2a05 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/style.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled, Box, Chip } from "@mui/material"; import mapbackground from "../../../../../../assets/img/mapbackground.png"; import { getTextColor, RGB } from "./utils"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts index 1117d461a5..2025d4a71d 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo } from "react"; import { StudyLayer } from "../../../../../../common/types"; import { StudyMapNode } from "../../../../../../redux/ducks/studyMaps"; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/index.tsx index 435d8b59c2..629e345f3c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useMemo } from "react"; import { useNavigate, useOutletContext, useParams } from "react-router-dom"; import { Box } from "@mui/material"; diff --git a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx index daa10520c2..7beaf0ec2a 100644 --- a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Skeleton, @@ -46,7 +60,7 @@ import BooleanFE from "../../../../../common/fieldEditors/BooleanFE"; import SelectFE from "../../../../../common/fieldEditors/SelectFE"; import NumberFE from "../../../../../common/fieldEditors/NumberFE"; import moment from "moment"; -import DownloadMatrixButton from "../../../../../common/DownloadMatrixButton.tsx"; +import DownloadMatrixButton from "../../../../../common/buttons/DownloadMatrixButton.tsx"; function ResultDetails() { const { study } = useOutletContext<{ study: StudyMetadata }>(); diff --git a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/utils.ts b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/utils.ts index cba62478c8..042cc80bba 100644 --- a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Area, LinkElement, Simulation } from "../../../../../../common/types"; export enum OutputItemType { diff --git a/webapp/src/components/App/Singlestudy/explore/Results/index.tsx b/webapp/src/components/App/Singlestudy/explore/Results/index.tsx index fa760c41ad..ea3c94a351 100644 --- a/webapp/src/components/App/Singlestudy/explore/Results/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Results/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, CircularProgress, diff --git a/webapp/src/components/App/Singlestudy/explore/TabWrapper.tsx b/webapp/src/components/App/Singlestudy/explore/TabWrapper.tsx index 3f04932134..5c7ac6dd03 100644 --- a/webapp/src/components/App/Singlestudy/explore/TabWrapper.tsx +++ b/webapp/src/components/App/Singlestudy/explore/TabWrapper.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import * as React from "react"; import { styled, SxProps, Theme } from "@mui/material"; diff --git a/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/CreateTemplateTableDialog.tsx b/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/CreateTemplateTableDialog.tsx index 9e5c223f6f..34da75ba1a 100644 --- a/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/CreateTemplateTableDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/CreateTemplateTableDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import AddCircleIcon from "@mui/icons-material/AddCircle"; import { createTableTemplate, type TableTemplate } from "../utils"; diff --git a/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/TableTemplateFormDialog.tsx b/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/TableTemplateFormDialog.tsx index 0b49e7335c..f019b529d5 100644 --- a/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/TableTemplateFormDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/TableTemplateFormDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box } from "@mui/material"; import { startCase } from "lodash"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/UpdateTemplateTableDialog.tsx b/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/UpdateTemplateTableDialog.tsx index ba8569d0a3..bf602db8dd 100644 --- a/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/UpdateTemplateTableDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/TableModeList/dialogs/UpdateTemplateTableDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import EditIcon from "@mui/icons-material/Edit"; import TableTemplateFormDialog, { diff --git a/webapp/src/components/App/Singlestudy/explore/TableModeList/index.tsx b/webapp/src/components/App/Singlestudy/explore/TableModeList/index.tsx index 161fe55c2f..ab4dcd787c 100644 --- a/webapp/src/components/App/Singlestudy/explore/TableModeList/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/TableModeList/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { MenuItem } from "@mui/material"; import { useOutletContext } from "react-router"; diff --git a/webapp/src/components/App/Singlestudy/explore/TableModeList/utils.ts b/webapp/src/components/App/Singlestudy/explore/TableModeList/utils.ts index e09d068ab2..8ded338463 100644 --- a/webapp/src/components/App/Singlestudy/explore/TableModeList/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/TableModeList/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { v4 as uuidv4 } from "uuid"; import { TableModeColumnsForType, diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CandidateForm.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CandidateForm.tsx index f2bdb8c89f..bb74aac2ad 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CandidateForm.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CandidateForm.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState, useEffect } from "react"; import { Box, diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx index eca88218e4..8cda654de0 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo, useState } from "react"; import { Button, ButtonGroup } from "@mui/material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/XpansionPropsView.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/XpansionPropsView.tsx index c2bd1f5b70..6da12c7a73 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/XpansionPropsView.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/XpansionPropsView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback, useEffect, useState } from "react"; import { Box, Button } from "@mui/material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/index.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/index.tsx index 42e7307f1d..66d41de0c2 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { useOutletContext, useNavigate } from "react-router-dom"; import { AxiosError } from "axios"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Capacities.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Capacities.tsx index cf56870b35..8d6fbdeb92 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Capacities.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Capacities.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { getAllCapacities, deleteCapacity, diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Constraints.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Constraints.tsx index 65af583a90..9143c0abe7 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Constraints.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Constraints.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { getAllConstraints, deleteConstraints, diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/FileList.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/FileList.tsx index 2c80263fa8..e4e291caf1 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/FileList.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/FileList.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { useOutletContext } from "react-router-dom"; import { AxiosError } from "axios"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/SettingsForm.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/SettingsForm.tsx index 8a7298e2e5..259845da99 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/SettingsForm.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/SettingsForm.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState, useEffect } from "react"; import { Box, Divider, Typography, Button, TextField } from "@mui/material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/index.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/index.tsx index aee2c9f4c7..a3b01a4b9b 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Settings/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { useOutletContext } from "react-router-dom"; import { AxiosError } from "axios"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Weights.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Weights.tsx index 83d3693f98..3e18632c72 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Weights.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Weights.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { addWeight, deleteWeight, diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/index.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/index.tsx index e242532f23..6f56a96318 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable react-hooks/exhaustive-deps */ import { useEffect, useMemo, useState } from "react"; import { AxiosError } from "axios"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/share/styles.ts b/webapp/src/components/App/Singlestudy/explore/Xpansion/share/styles.ts index 864b9e084a..96fb5dbd31 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/share/styles.ts +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/share/styles.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Typography, Button, styled } from "@mui/material"; import VisibilityIcon from "@mui/icons-material/Visibility"; import DeleteIcon from "@mui/icons-material/Delete"; diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/types.ts b/webapp/src/components/App/Singlestudy/explore/Xpansion/types.ts index b8e7a39888..84b190dda5 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/types.ts +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/types.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + export interface XpansionSensitivitySettings { epsilon: number; capex: boolean; diff --git a/webapp/src/components/App/Singlestudy/explore/common/ListElement.tsx b/webapp/src/components/App/Singlestudy/explore/common/ListElement.tsx index 4292cd7324..69b9254d61 100644 --- a/webapp/src/components/App/Singlestudy/explore/common/ListElement.tsx +++ b/webapp/src/components/App/Singlestudy/explore/common/ListElement.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, ListItemButton, diff --git a/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx b/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx index 046ada24c3..39cef64ff6 100644 --- a/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx +++ b/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo } from "react"; import { FieldPath } from "react-hook-form"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Singlestudy/explore/common/types.ts b/webapp/src/components/App/Singlestudy/explore/common/types.ts index 7dbbc82e08..c9ae042882 100644 --- a/webapp/src/components/App/Singlestudy/explore/common/types.ts +++ b/webapp/src/components/App/Singlestudy/explore/common/types.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + export type FilteringType = | "hourly" | "daily" diff --git a/webapp/src/components/App/Singlestudy/index.tsx b/webapp/src/components/App/Singlestudy/index.tsx index 1900d81cfb..e7eedfe7a9 100644 --- a/webapp/src/components/App/Singlestudy/index.tsx +++ b/webapp/src/components/App/Singlestudy/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable react-hooks/exhaustive-deps */ import { useEffect, useCallback, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; @@ -195,8 +209,4 @@ function SingleStudy(props: Props) { ); } -SingleStudy.defaultProps = { - isExplorer: undefined, -}; - export default SingleStudy; diff --git a/webapp/src/components/App/Studies/BatchModeMenu.tsx b/webapp/src/components/App/Studies/BatchModeMenu.tsx index c7bdf92e28..a301b4e27f 100644 --- a/webapp/src/components/App/Studies/BatchModeMenu.tsx +++ b/webapp/src/components/App/Studies/BatchModeMenu.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import BoltIcon from "@mui/icons-material/Bolt"; import { Box, Button, IconButton, Tooltip } from "@mui/material"; import { t } from "i18next"; diff --git a/webapp/src/components/App/Studies/CreateStudyDialog.tsx b/webapp/src/components/App/Studies/CreateStudyDialog.tsx index 97ef0399cf..c90a52cf5a 100644 --- a/webapp/src/components/App/Studies/CreateStudyDialog.tsx +++ b/webapp/src/components/App/Studies/CreateStudyDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import debug from "debug"; import { useSnackbar } from "notistack"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/index.tsx b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/index.tsx index 446bef67a9..91b0c285b6 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Chip, ListItem } from "@mui/material"; import { useState } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/style.ts b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/style.ts index 7feae7fb79..4528d39b84 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/style.ts +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/MultipleLinkElement/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, List, styled } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/index.tsx b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/index.tsx index 0cef1d0190..961d7a6929 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, TextField } from "@mui/material"; import { useState } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/style.ts b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/style.ts index f964d5e250..5c9b66e87a 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/style.ts +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/SingleLinkElement/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, styled } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/index.tsx b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/index.tsx index cffc673c9e..d64fc9665d 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { TextField } from "@mui/material"; diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/style.ts b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/style.ts index 48549e3035..870740514c 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/style.ts +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/Filter/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, styled } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/index.tsx b/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/index.tsx index ba4d1bca14..4ea269470f 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { Chip, ListItem, TextField } from "@mui/material"; import { AddIcon, InputContainer, Root, TagContainer } from "./style"; diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/style.ts b/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/style.ts index dae66af295..b043b11320 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/style.ts +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/TagSelect/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, List, styled } from "@mui/material"; import AddCircleOutlinedIcon from "@mui/icons-material/AddCircleOutlined"; diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx b/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx index e7a7fc9e85..a03d0f22fe 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import _ from "lodash"; diff --git a/webapp/src/components/App/Studies/ExportModal/index.tsx b/webapp/src/components/App/Studies/ExportModal/index.tsx index aa0805437f..d9d24714cf 100644 --- a/webapp/src/components/App/Studies/ExportModal/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ReactNode, useEffect, useState } from "react"; import * as R from "ramda"; import { AxiosError } from "axios"; diff --git a/webapp/src/components/App/Studies/FilterDrawer.tsx b/webapp/src/components/App/Studies/FilterDrawer.tsx index 5a613d7a6a..676fb27f91 100644 --- a/webapp/src/components/App/Studies/FilterDrawer.tsx +++ b/webapp/src/components/App/Studies/FilterDrawer.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import Box from "@mui/material/Box"; import Toolbar from "@mui/material/Toolbar"; diff --git a/webapp/src/components/App/Studies/HeaderBottom.tsx b/webapp/src/components/App/Studies/HeaderBottom.tsx index da107facd7..bfab7c6511 100644 --- a/webapp/src/components/App/Studies/HeaderBottom.tsx +++ b/webapp/src/components/App/Studies/HeaderBottom.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, Chip, Divider } from "@mui/material"; import { useTranslation } from "react-i18next"; import { indigo, purple } from "@mui/material/colors"; diff --git a/webapp/src/components/App/Studies/HeaderTopRight.tsx b/webapp/src/components/App/Studies/HeaderTopRight.tsx index 86b5228758..117658f834 100644 --- a/webapp/src/components/App/Studies/HeaderTopRight.tsx +++ b/webapp/src/components/App/Studies/HeaderTopRight.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Button } from "@mui/material"; import { useState } from "react"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Studies/LauncherDialog.tsx b/webapp/src/components/App/Studies/LauncherDialog.tsx index 670cb54cdc..5a000a9a7d 100644 --- a/webapp/src/components/App/Studies/LauncherDialog.tsx +++ b/webapp/src/components/App/Studies/LauncherDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { Box, diff --git a/webapp/src/components/App/Studies/MoveStudyDialog.tsx b/webapp/src/components/App/Studies/MoveStudyDialog.tsx index e451c31215..e3698438a5 100644 --- a/webapp/src/components/App/Studies/MoveStudyDialog.tsx +++ b/webapp/src/components/App/Studies/MoveStudyDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DialogProps } from "@mui/material"; import TextField from "@mui/material/TextField"; import { useSnackbar } from "notistack"; diff --git a/webapp/src/components/App/Studies/RefreshButton.tsx b/webapp/src/components/App/Studies/RefreshButton.tsx index 122ab202bb..cf158c4fe7 100644 --- a/webapp/src/components/App/Studies/RefreshButton.tsx +++ b/webapp/src/components/App/Studies/RefreshButton.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Button, Tooltip } from "@mui/material"; import RefreshIcon from "@mui/icons-material/Refresh"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Studies/SideNav.tsx b/webapp/src/components/App/Studies/SideNav.tsx index d1e2f7ac38..c0009ce7d2 100644 --- a/webapp/src/components/App/Studies/SideNav.tsx +++ b/webapp/src/components/App/Studies/SideNav.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useNavigate } from "react-router"; import { Box, Typography, List, ListItem, ListItemText } from "@mui/material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Studies/StudiesList/StudyCardCell.tsx b/webapp/src/components/App/Studies/StudiesList/StudyCardCell.tsx index cf5dd75955..64cfec20c3 100644 --- a/webapp/src/components/App/Studies/StudiesList/StudyCardCell.tsx +++ b/webapp/src/components/App/Studies/StudiesList/StudyCardCell.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { memo } from "react"; import { Box, Skeleton } from "@mui/material"; import { GridChildComponentProps, areEqual } from "react-window"; diff --git a/webapp/src/components/App/Studies/StudiesList/index.tsx b/webapp/src/components/App/Studies/StudiesList/index.tsx index 65c8befbf9..a6c412e625 100644 --- a/webapp/src/components/App/Studies/StudiesList/index.tsx +++ b/webapp/src/components/App/Studies/StudiesList/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Box, diff --git a/webapp/src/components/App/Studies/StudyCard.tsx b/webapp/src/components/App/Studies/StudyCard.tsx index 4df2222511..79c0c6b991 100644 --- a/webapp/src/components/App/Studies/StudyCard.tsx +++ b/webapp/src/components/App/Studies/StudyCard.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { memo, useState } from "react"; import { NavLink, useNavigate } from "react-router-dom"; import { AxiosError } from "axios"; diff --git a/webapp/src/components/App/Studies/StudyTree.tsx b/webapp/src/components/App/Studies/StudyTree.tsx index e4876e8790..638d475f50 100644 --- a/webapp/src/components/App/Studies/StudyTree.tsx +++ b/webapp/src/components/App/Studies/StudyTree.tsx @@ -1,99 +1,69 @@ -import { useCallback, Fragment } from "react"; -import { Typography } from "@mui/material"; -import TreeView from "@mui/lab/TreeView"; -import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import ChevronRightIcon from "@mui/icons-material/ChevronRight"; -import TreeItem from "@mui/lab/TreeItem"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyTreeNode } from "./utils"; import useAppSelector from "../../../redux/hooks/useAppSelector"; import { getStudiesTree, getStudyFilters } from "../../../redux/selectors"; import useAppDispatch from "../../../redux/hooks/useAppDispatch"; import { updateStudyFilters } from "../../../redux/ducks/studies"; +import TreeItemEnhanced from "../../common/TreeItemEnhanced"; +import { SimpleTreeView } from "@mui/x-tree-view/SimpleTreeView"; +import { getParentPaths } from "../../../utils/pathUtils"; +import * as R from "ramda"; function StudyTree() { - const folder = useAppSelector((state) => getStudyFilters(state).folder); + const folder = useAppSelector((state) => getStudyFilters(state).folder, R.T); const studiesTree = useAppSelector(getStudiesTree); const dispatch = useAppDispatch(); - const getExpandedTab = (nodeId: string): string[] => { - const expandedTab: string[] = []; - const tab = nodeId.split("/"); - let lastnodeId = ""; - for (let i = 0; i < tab.length; i += 1) { - lastnodeId += i === 0 ? tab[i] : `/${tab[i]}`; - expandedTab.push(lastnodeId); - } - return expandedTab; + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleTreeItemClick = (itemId: string) => { + dispatch(updateStudyFilters({ folder: itemId })); }; - const buildTree = (children: StudyTreeNode[], parentId: string) => - children.map((elm) => { - const newId = `${parentId}/${elm.name}`; + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + const buildTree = (children: StudyTreeNode[], parentId?: string) => { + return children.map((elm) => { + const id = parentId ? `${parentId}/${elm.name}` : elm.name; + return ( - - { - e.preventDefault(); - e.stopPropagation(); - dispatch(updateStudyFilters({ folder: newId })); - }} - > - {elm.name} - - } - collapseIcon={ - elm.children.length > 0 ? : undefined - } - expandIcon={ - elm.children.length > 0 ? : undefined - } - > - {buildTree((elm as StudyTreeNode).children, newId)} - - + handleTreeItemClick(id)} + > + {buildTree(elm.children, id)} + ); }); - // eslint-disable-next-line react-hooks/exhaustive-deps - const getDefaultSelected = useCallback(() => [folder], []); - - // eslint-disable-next-line react-hooks/exhaustive-deps - const getDefaultExpanded = useCallback(() => getExpandedTab(folder), []); + }; return ( - - { - e.preventDefault(); - e.stopPropagation(); - dispatch(updateStudyFilters({ folder: studiesTree.name })); - }} - > - {studiesTree.name} - - } - collapseIcon={ - studiesTree.children.length > 0 ? : undefined - } - expandIcon={ - studiesTree.children.length > 0 ? : undefined - } - > - {buildTree(studiesTree.children, studiesTree.name)} - - + {buildTree([studiesTree])} + ); } diff --git a/webapp/src/components/App/Studies/index.tsx b/webapp/src/components/App/Studies/index.tsx index c0ac35eac9..f422ce3249 100644 --- a/webapp/src/components/App/Studies/index.tsx +++ b/webapp/src/components/App/Studies/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { Box, Divider } from "@mui/material"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/App/Studies/utils.ts b/webapp/src/components/App/Studies/utils.ts index 9da96074a5..dc2d1c5396 100644 --- a/webapp/src/components/App/Studies/utils.ts +++ b/webapp/src/components/App/Studies/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyMetadata } from "../../../common/types"; export interface StudyTreeNode { diff --git a/webapp/src/components/App/Tasks/JobTableView.tsx b/webapp/src/components/App/Tasks/JobTableView.tsx index 506c95762e..5f8a34b674 100644 --- a/webapp/src/components/App/Tasks/JobTableView.tsx +++ b/webapp/src/components/App/Tasks/JobTableView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback, useEffect, useState } from "react"; import moment from "moment"; import { diff --git a/webapp/src/components/App/Tasks/LaunchJobLogView.tsx b/webapp/src/components/App/Tasks/LaunchJobLogView.tsx index 0fc2869005..d7c5b4c22a 100644 --- a/webapp/src/components/App/Tasks/LaunchJobLogView.tsx +++ b/webapp/src/components/App/Tasks/LaunchJobLogView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { AxiosError } from "axios"; import { useTranslation } from "react-i18next"; @@ -118,9 +132,4 @@ function LaunchJobLogView(props: PropsType) { ); } -LaunchJobLogView.defaultProps = { - logButton: false, - logErrorButton: false, -}; - export default LaunchJobLogView; diff --git a/webapp/src/components/App/Tasks/NotificationBadge.tsx b/webapp/src/components/App/Tasks/NotificationBadge.tsx index 6a7715fa98..499a327d71 100644 --- a/webapp/src/components/App/Tasks/NotificationBadge.tsx +++ b/webapp/src/components/App/Tasks/NotificationBadge.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ReactNode, useCallback, useEffect, useRef } from "react"; import debug from "debug"; import { Box, Typography } from "@mui/material"; diff --git a/webapp/src/components/App/Tasks/index.tsx b/webapp/src/components/App/Tasks/index.tsx index 11c8a7f525..6f756c49b6 100644 --- a/webapp/src/components/App/Tasks/index.tsx +++ b/webapp/src/components/App/Tasks/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable react-hooks/exhaustive-deps */ import { useState, useEffect, useMemo } from "react"; import { AxiosError } from "axios"; diff --git a/webapp/src/components/App/index.tsx b/webapp/src/components/App/index.tsx index 35e1714e09..18cb04f537 100644 --- a/webapp/src/components/App/index.tsx +++ b/webapp/src/components/App/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { BrowserRouter as Router, Navigate, diff --git a/webapp/src/components/common/ButtonBack.tsx b/webapp/src/components/common/ButtonBack.tsx index 0af4de5418..49fd1a5355 100644 --- a/webapp/src/components/common/ButtonBack.tsx +++ b/webapp/src/components/common/ButtonBack.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button } from "@mui/material"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/common/DocLink.tsx b/webapp/src/components/common/DocLink.tsx index aa2e811fc9..48e5468701 100644 --- a/webapp/src/components/common/DocLink.tsx +++ b/webapp/src/components/common/DocLink.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Help } from "@mui/icons-material"; import { Tooltip, IconButton, SxProps, Theme } from "@mui/material"; diff --git a/webapp/src/components/common/DownloadLink.tsx b/webapp/src/components/common/DownloadLink.tsx index ec67f0b674..1f3b45894d 100644 --- a/webapp/src/components/common/DownloadLink.tsx +++ b/webapp/src/components/common/DownloadLink.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { IconButton, Tooltip } from "@mui/material"; import { ReactElement } from "react"; import { refresh } from "../../redux/ducks/auth"; diff --git a/webapp/src/components/common/DownloadMatrixButton.tsx b/webapp/src/components/common/DownloadMatrixButton.tsx deleted file mode 100644 index 49551eb0f7..0000000000 --- a/webapp/src/components/common/DownloadMatrixButton.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import FileUploadIcon from "@mui/icons-material/FileUpload"; -import SplitButton from "./buttons/SplitButton.tsx"; -import { downloadMatrix } from "../../services/api/studies/raw/index.ts"; -import { downloadFile } from "../../utils/fileUtils.ts"; -import { useState } from "react"; -import { StudyMetadata } from "../../common/types.ts"; -import useEnqueueErrorSnackbar from "../../hooks/useEnqueueErrorSnackbar.tsx"; -import { useTranslation } from "react-i18next"; - -export interface DownloadMatrixButtonProps { - studyId: StudyMetadata["id"]; - path?: string; - disabled?: boolean; - label?: string; -} - -const EXPORT_OPTIONS = [ - { label: "TSV", value: "tsv" }, - { label: "Excel", value: "xlsx" }, -] as const; - -type ExportFormat = (typeof EXPORT_OPTIONS)[number]["value"]; - -function DownloadMatrixButton(props: DownloadMatrixButtonProps) { - const { t } = useTranslation(); - const { studyId, path, disabled, label = t("global.export") } = props; - const [isDownloading, setIsDownloading] = useState(false); - const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); - - //////////////////////////////////////////////////////////////// - // Event Handlers - //////////////////////////////////////////////////////////////// - - const handleDownload = async (format: ExportFormat) => { - if (!path) { - return; - } - - setIsDownloading(true); - - const isExcel = format === "xlsx"; - - try { - const res = await downloadMatrix({ - studyId, - path, - format, - header: isExcel, - index: isExcel, - }); - - downloadFile( - res, - `matrix_${studyId}_${path.replace("/", "_")}.${format}`, - ); - } catch (err) { - enqueueErrorSnackbar(t("global.download.error"), String(err)); - } - - setIsDownloading(false); - }; - - //////////////////////////////////////////////////////////////// - // JSX - //////////////////////////////////////////////////////////////// - - return ( - , - loadingPosition: "start", - loading: isDownloading, - }} - > - {label} - - ); -} - -export default DownloadMatrixButton; diff --git a/webapp/src/components/common/DynamicDataTable/TableRowGroup.tsx b/webapp/src/components/common/DynamicDataTable/TableRowGroup.tsx index 6022a6e3a0..523694704a 100644 --- a/webapp/src/components/common/DynamicDataTable/TableRowGroup.tsx +++ b/webapp/src/components/common/DynamicDataTable/TableRowGroup.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TableRow, TableCell, diff --git a/webapp/src/components/common/DynamicDataTable/TableRowItem.tsx b/webapp/src/components/common/DynamicDataTable/TableRowItem.tsx index fa7ad0047b..214a84a730 100644 --- a/webapp/src/components/common/DynamicDataTable/TableRowItem.tsx +++ b/webapp/src/components/common/DynamicDataTable/TableRowItem.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TableCell, Checkbox, Chip, TableRow } from "@mui/material"; import { ChangeEvent, memo, useCallback } from "react"; import { Item, Column } from "./utils"; diff --git a/webapp/src/components/common/DynamicDataTable/TableToolbar.tsx b/webapp/src/components/common/DynamicDataTable/TableToolbar.tsx index 25efc3fb09..7364176e7b 100644 --- a/webapp/src/components/common/DynamicDataTable/TableToolbar.tsx +++ b/webapp/src/components/common/DynamicDataTable/TableToolbar.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Toolbar, alpha, diff --git a/webapp/src/components/common/DynamicDataTable/index.tsx b/webapp/src/components/common/DynamicDataTable/index.tsx index 96d67feeb9..6d00babf94 100644 --- a/webapp/src/components/common/DynamicDataTable/index.tsx +++ b/webapp/src/components/common/DynamicDataTable/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import Box from "@mui/material/Box"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; diff --git a/webapp/src/components/common/DynamicDataTable/utils.ts b/webapp/src/components/common/DynamicDataTable/utils.ts index b805053234..3818fc3bd8 100644 --- a/webapp/src/components/common/DynamicDataTable/utils.ts +++ b/webapp/src/components/common/DynamicDataTable/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ChipProps } from "@mui/material"; //////////////////////////////////////////////////////////////// diff --git a/webapp/src/components/common/DynamicList.tsx b/webapp/src/components/common/DynamicList.tsx index db4198c956..d0ce83e085 100644 --- a/webapp/src/components/common/DynamicList.tsx +++ b/webapp/src/components/common/DynamicList.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import React from "react"; import { Grid, Divider, IconButton } from "@mui/material"; import { t } from "i18next"; diff --git a/webapp/src/components/common/EditableMatrix/MatrixGraphView.tsx b/webapp/src/components/common/EditableMatrix/MatrixGraphView.tsx index b6fd0b33b3..765f991b03 100644 --- a/webapp/src/components/common/EditableMatrix/MatrixGraphView.tsx +++ b/webapp/src/components/common/EditableMatrix/MatrixGraphView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import Plot from "react-plotly.js"; import AutoSizer from "react-virtualized-auto-sizer"; diff --git a/webapp/src/components/common/EditableMatrix/index.tsx b/webapp/src/components/common/EditableMatrix/index.tsx index 7916fa2a1f..42802118eb 100644 --- a/webapp/src/components/common/EditableMatrix/index.tsx +++ b/webapp/src/components/common/EditableMatrix/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState, useRef } from "react"; import debug from "debug"; import HT from "handsontable"; diff --git a/webapp/src/components/common/EditableMatrix/style.ts b/webapp/src/components/common/EditableMatrix/style.ts index dd62aecfd2..dcd6dc3159 100644 --- a/webapp/src/components/common/EditableMatrix/style.ts +++ b/webapp/src/components/common/EditableMatrix/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled, Box, Button } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/common/EditableMatrix/utils.ts b/webapp/src/components/common/EditableMatrix/utils.ts index 3daa633e8f..aed63af7e7 100644 --- a/webapp/src/components/common/EditableMatrix/utils.ts +++ b/webapp/src/components/common/EditableMatrix/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import _ from "lodash"; import moment, { DurationInputArg2 } from "moment"; import HT from "handsontable"; diff --git a/webapp/src/components/common/Fieldset.tsx b/webapp/src/components/common/Fieldset.tsx index 442e4078b6..081a9accce 100644 --- a/webapp/src/components/common/Fieldset.tsx +++ b/webapp/src/components/common/Fieldset.tsx @@ -1,13 +1,28 @@ -import { Box, BoxProps, Divider, Typography } from "@mui/material"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { Box, BoxProps, Divider, SxProps, Theme } from "@mui/material"; import * as RA from "ramda-adjunct"; import { mergeSxProp } from "../../utils/muiUtils"; -interface FieldsetProps extends Omit { +interface FieldsetProps { legend?: string | React.ReactNode; children: React.ReactNode; contentProps?: BoxProps; fullFieldWidth?: boolean; fieldWidth?: number; + sx?: SxProps; } function Fieldset(props: FieldsetProps) { @@ -18,19 +33,17 @@ function Fieldset(props: FieldsetProps) { contentProps, fullFieldWidth = false, fieldWidth = 220, - ...rest } = props; return ( .MuiBox-root": { display: "flex", flexWrap: "wrap", @@ -40,6 +53,10 @@ function Fieldset(props: FieldsetProps) { m: 0, }, }, + // Increase padding from the last child + ".Form__Content > &:last-child": { + pb: 2, + }, // Remove padding from the last child of the dialog content ".MuiDialogContent-root .Form__Content > &:last-child": { pb: 0, @@ -51,19 +68,14 @@ function Fieldset(props: FieldsetProps) { {legend && ( <> {RA.isString(legend) ? ( - - {legend} - + {legend} ) : ( legend )} )} - + {children} diff --git a/webapp/src/components/common/FileTable.tsx b/webapp/src/components/common/FileTable.tsx index bec4ed2338..9ffac99fd6 100644 --- a/webapp/src/components/common/FileTable.tsx +++ b/webapp/src/components/common/FileTable.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ReactNode, useState } from "react"; import { Box, @@ -223,14 +237,4 @@ function FileTable(props: PropType) { ); } -FileTable.defaultProps = { - onDelete: undefined, - onAssign: undefined, - uploadFile: undefined, - allowImport: false, - allowDelete: false, - onFileDownload: undefined, - copyId: false, -}; - export default FileTable; diff --git a/webapp/src/components/common/Form/FormContext.tsx b/webapp/src/components/common/Form/FormContext.tsx index 9a4d8bc376..64ecd0d35e 100644 --- a/webapp/src/components/common/Form/FormContext.tsx +++ b/webapp/src/components/common/Form/FormContext.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createContext } from "react"; const FormContext = createContext({ isAutoSubmitEnabled: false }); diff --git a/webapp/src/components/common/Form/index.tsx b/webapp/src/components/common/Form/index.tsx index c14bc783be..da4bcca048 100644 --- a/webapp/src/components/common/Form/index.tsx +++ b/webapp/src/components/common/Form/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ import { FormEvent, useEffect, useMemo, useRef, useState } from "react"; import { diff --git a/webapp/src/components/common/Form/types.ts b/webapp/src/components/common/Form/types.ts index 0d8010e287..d7f27f94fb 100644 --- a/webapp/src/components/common/Form/types.ts +++ b/webapp/src/components/common/Form/types.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ import { Control, diff --git a/webapp/src/components/common/Form/useFormApiPlus.ts b/webapp/src/components/common/Form/useFormApiPlus.ts index f0b7a3947d..be3239d69a 100644 --- a/webapp/src/components/common/Form/useFormApiPlus.ts +++ b/webapp/src/components/common/Form/useFormApiPlus.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { BatchFieldArrayUpdate, FieldPath, diff --git a/webapp/src/components/common/Form/useFormUndoRedo.ts b/webapp/src/components/common/Form/useFormUndoRedo.ts index db435d1395..9d3fec2158 100644 --- a/webapp/src/components/common/Form/useFormUndoRedo.ts +++ b/webapp/src/components/common/Form/useFormUndoRedo.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import useUndo, { Actions } from "use-undo"; import { FieldValues } from "react-hook-form"; import { useCallback, useEffect, useRef } from "react"; diff --git a/webapp/src/components/common/Form/utils.ts b/webapp/src/components/common/Form/utils.ts index 3a07564d39..e01e882708 100644 --- a/webapp/src/components/common/Form/utils.ts +++ b/webapp/src/components/common/Form/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as RA from "ramda-adjunct"; import { AutoSubmitConfig, FormProps } from "."; diff --git a/webapp/src/components/common/GroupedDataTable/CreateDialog.tsx b/webapp/src/components/common/GroupedDataTable/CreateDialog.tsx index 9df4f4e2c5..60a23e7c58 100644 --- a/webapp/src/components/common/GroupedDataTable/CreateDialog.tsx +++ b/webapp/src/components/common/GroupedDataTable/CreateDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import AddCircleIcon from "@mui/icons-material/AddCircle"; import FormDialog from "../dialogs/FormDialog"; import StringFE from "../fieldEditors/StringFE"; diff --git a/webapp/src/components/common/GroupedDataTable/DuplicateDialog.tsx b/webapp/src/components/common/GroupedDataTable/DuplicateDialog.tsx index 099748ef9a..5043bc8d53 100644 --- a/webapp/src/components/common/GroupedDataTable/DuplicateDialog.tsx +++ b/webapp/src/components/common/GroupedDataTable/DuplicateDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import ContentCopyIcon from "@mui/icons-material/ContentCopy"; import Fieldset from "../Fieldset"; diff --git a/webapp/src/components/common/GroupedDataTable/cellRenderers/BooleanCell.tsx b/webapp/src/components/common/GroupedDataTable/cellRenderers/BooleanCell.tsx index deb28e01a2..b59c496854 100644 --- a/webapp/src/components/common/GroupedDataTable/cellRenderers/BooleanCell.tsx +++ b/webapp/src/components/common/GroupedDataTable/cellRenderers/BooleanCell.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Chip } from "@mui/material"; import type { MRT_Cell, MRT_RowData } from "material-react-table"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/common/GroupedDataTable/index.tsx b/webapp/src/components/common/GroupedDataTable/index.tsx index 6aed12cc32..5dd2081773 100644 --- a/webapp/src/components/common/GroupedDataTable/index.tsx +++ b/webapp/src/components/common/GroupedDataTable/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import Box from "@mui/material/Box"; import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline"; import ContentCopyIcon from "@mui/icons-material/ContentCopy"; @@ -420,7 +434,7 @@ function GroupedDataTable< > {RA.isFunction(deleteConfirmationMessage) ? deleteConfirmationMessage(selectedRows.length) - : deleteConfirmationMessage ?? t("dialog.message.confirmDelete")} + : (deleteConfirmationMessage ?? t("dialog.message.confirmDelete"))} )} diff --git a/webapp/src/components/common/GroupedDataTable/types.ts b/webapp/src/components/common/GroupedDataTable/types.ts index 6f91852cb4..ba267f9f4b 100644 --- a/webapp/src/components/common/GroupedDataTable/types.ts +++ b/webapp/src/components/common/GroupedDataTable/types.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + export interface TRow { name: string; group: T; diff --git a/webapp/src/components/common/GroupedDataTable/utils.ts b/webapp/src/components/common/GroupedDataTable/utils.ts index f209d83bae..07b670d25a 100644 --- a/webapp/src/components/common/GroupedDataTable/utils.ts +++ b/webapp/src/components/common/GroupedDataTable/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; import { TableCellProps } from "@mui/material"; import type { TRow } from "./types"; diff --git a/webapp/src/components/common/Handsontable.tsx b/webapp/src/components/common/Handsontable.tsx index 2434eff01d..0e6d6c3f8a 100644 --- a/webapp/src/components/common/Handsontable.tsx +++ b/webapp/src/components/common/Handsontable.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { registerAllModules } from "handsontable/registry"; import HotTable, { HotTableProps } from "@handsontable/react"; import { styled } from "@mui/material"; diff --git a/webapp/src/components/common/JSONEditor/index.tsx b/webapp/src/components/common/JSONEditor/index.tsx index 6c7a0c19b5..a38587ae45 100644 --- a/webapp/src/components/common/JSONEditor/index.tsx +++ b/webapp/src/components/common/JSONEditor/index.tsx @@ -1,40 +1,200 @@ -import JSONEditorLib, { JSONEditorOptions } from "jsoneditor"; -import { useRef } from "react"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import JSONEditorClass, { + type JSONEditorOptions, + type HistoryItem, +} from "jsoneditor"; +import { useMemo, useRef } from "react"; import { useDeepCompareEffect, useMount } from "react-use"; import "jsoneditor/dist/jsoneditor.min.css"; import "./dark-theme.css"; +import { PromiseAny } from "../../../utils/tsUtils"; +import useAutoUpdateRef from "../../../hooks/useAutoUpdateRef"; +import { createSaveButton } from "./utils"; +import * as R from "ramda"; +import * as RA from "ramda-adjunct"; +import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar"; +import { toError } from "../../../utils/fnUtils"; +import { Box } from "@mui/material"; -interface JSONEditorProps extends JSONEditorOptions { - // eslint-disable-next-line @typescript-eslint/no-explicit-any +export interface JSONEditorProps extends JSONEditorOptions { json: any; + onSave?: (json: any) => PromiseAny; + onSaveSuccessful?: (json: any) => any; } -function JSONEditor({ json, ...options }: JSONEditorProps) { +function JSONEditor(props: JSONEditorProps) { + const { json, onSave, onSaveSuccessful, ...options } = props; const ref = useRef(null); - const editorRef = useRef(); + const editorRef = useRef(); + const onSaveRef = useAutoUpdateRef(onSave); + const callbackOptionsRef = useAutoUpdateRef>( + R.pickBy(RA.isFunction, options), + ); + const saveBtn = useMemo(() => createSaveButton(handleSaveClick), []); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + + /** + * The history item corresponding to the saved JSON. + * Only for some modes. + */ + const presentHistoryItem = useRef(null); + // Initialize the JSON editor useMount(() => { if (!ref.current) { return; } - const editor = new JSONEditorLib(ref.current, options); + const editor = new JSONEditorClass(ref.current, { + ...options, + ...callbackOptionsRef.current, + onChange: handleChange, + onModeChange: handleModeChange, + }); editor.set(json); + editorRef.current = editor; + initSave(); + return () => editor.destroy(); }); + // Update JSON when `json` prop change useDeepCompareEffect(() => { - if (!editorRef.current) { - return; - } + const editor = editorRef.current; - editorRef.current.set(json); - editorRef.current.expandAll(); + if (editor) { + editor.set(json); + editor.expandAll?.(); + } }, [json]); - return
; + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + function handleChange() { + callbackOptionsRef.current.onChange?.(); + + // Update the save button state + + const editor = editorRef.current; + + // Use undo/redo history to determine if the JSON is dirty + if (editor?.history?.history) { + updateSaveState( + presentHistoryItem.current !== + (editor.history.history[editor.history.index] ?? null), + ); + } else { + updateSaveState(true); + } + } + + function handleModeChange( + ...args: Parameters> + ) { + callbackOptionsRef.current.onModeChange?.(...args); + // Menu is reset when the mode changes + initSave(); + } + + async function handleSaveClick() { + const onSave = onSaveRef.current; + const editor = editorRef.current; + + if (onSave && editor) { + let json; + + try { + json = editor.get(); + } catch (err) { + enqueueErrorSnackbar("Invalid JSON", toError(err)); + return; + } + + try { + await onSave(json); + + updateSaveState(false); + onSaveSuccessful?.(json); + + presentHistoryItem.current = + editor?.history?.history?.[editor.history.index] ?? null; + } catch (err) { + enqueueErrorSnackbar("test", toError(err)); + } + } + } + + //////////////////////////////////////////////////////////////// + // Save + //////////////////////////////////////////////////////////////// + + function initSave() { + const editor = editorRef.current; + + presentHistoryItem.current = null; + saveBtn.remove(); + + if ( + // The save button is added to the menu only when the `onSave` callback is provided + onSaveRef.current && + editor && + ["tree", "form", "code", "text"].includes(editor.getMode()) + ) { + updateSaveState(false); + editor.menu.append(saveBtn); + } + } + + function updateSaveState(enable: boolean) { + // Update the save button style + saveBtn.style.opacity = enable ? "1" : "0.1"; + saveBtn.disabled = !enable; + + // Changing the mode resets undo/redo history and undo/redo are not available in all modes. + // So the change mode mode button is disabled when the JSON is dirty. + + const editorModeBtn = editorRef.current?.menu.querySelector( + "button.jsoneditor-modes", + ); + + if (enable) { + editorModeBtn?.setAttribute("disabled", ""); + } else { + editorModeBtn?.removeAttribute("disabled"); + } + } + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + + ); } export default JSONEditor; diff --git a/webapp/src/components/common/JSONEditor/utils.ts b/webapp/src/components/common/JSONEditor/utils.ts new file mode 100644 index 0000000000..c7760e3452 --- /dev/null +++ b/webapp/src/components/common/JSONEditor/utils.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import i18n from "../../../i18n"; + +export function createSaveButton(onClick: VoidFunction) { + const saveBtn = document.createElement("button"); + saveBtn.classList.add("jsoneditor-separator"); + saveBtn.title = i18n.t("global.save"); + saveBtn.style.backgroundImage = + "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7E" + + "AAAOxAGVKw4bAAAA6klEQVQ4jaXSMUoDYRQE4G+XJYhFkNR2ggewtvQE3kS09QQKIjmDWHsEwcIrWGulIiIhBh" + + "HHIptkDYlhdcr3v5l5/3tTJNlHHxu4wYPlqLCHM5wWRUGS+8ywuYiV5DzJdZJukqu69ySJCt1G79cS5x3sooPP" + + "unaEp7Iea5XAMhyXLQnzqCo0RdaXNF7iFkOsNR+KJO+N4iOef3Essd0wHc0LtMVossAXbNUjsniZza92cIfeRG" + + "BQFMVrC+ePJAP0JqptzzfllH8kT/HfHCjNovlngTc/49yGO6xwiH6SC+MzrtpJaZybHg6+AW/yWkXws02vAAAA" + + "AElFTkSuQmCC)"; + saveBtn.style.backgroundRepeat = "no-repeat"; + saveBtn.style.backgroundPosition = "center"; + + saveBtn.addEventListener("click", onClick); + + return saveBtn; +} diff --git a/webapp/src/components/common/LinearProgressWithLabel.tsx b/webapp/src/components/common/LinearProgressWithLabel.tsx index 853f8eab5a..642efd3a4d 100644 --- a/webapp/src/components/common/LinearProgressWithLabel.tsx +++ b/webapp/src/components/common/LinearProgressWithLabel.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Tooltip, Box, diff --git a/webapp/src/components/common/LogModal.tsx b/webapp/src/components/common/LogModal.tsx index 9c386e494c..b2b918a4db 100644 --- a/webapp/src/components/common/LogModal.tsx +++ b/webapp/src/components/common/LogModal.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback, useEffect, @@ -196,12 +210,4 @@ function LogModal(props: Props) { ); } -LogModal.defaultProps = { - content: undefined, - jobId: undefined, - followLogs: false, - loading: false, - style: {}, -}; - export default LogModal; diff --git a/webapp/src/components/common/MatrixGrid/Matrix.tsx b/webapp/src/components/common/MatrixGrid/Matrix.tsx new file mode 100644 index 0000000000..128bf480cc --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/Matrix.tsx @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { Divider, Skeleton } from "@mui/material"; +import MatrixGrid from "."; +import { useMatrix } from "./useMatrix"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import ImportDialog from "../dialogs/ImportDialog"; +import { useOutletContext } from "react-router"; +import { StudyMetadata } from "../../../common/types"; +import { MatrixContainer, MatrixHeader, MatrixTitle } from "./style"; +import MatrixActions from "./MatrixActions"; +import EmptyView from "../page/SimpleContent"; + +interface MatrixProps { + url: string; + title?: string; + enableTimeSeriesColumns?: boolean; + enableAggregateColumns?: boolean; +} + +function Matrix({ + url, + title = "global.timeSeries", + enableTimeSeriesColumns = true, + enableAggregateColumns = false, +}: MatrixProps) { + const { t } = useTranslation(); + const { study } = useOutletContext<{ study: StudyMetadata }>(); + const [openImportDialog, setOpenImportDialog] = useState(false); + + const { + data, + error, + isLoading, + isSubmitting, + columns, + dateTime, + handleCellEdit, + handleMultipleCellsEdit, + handleImport, + handleSaveUpdates, + pendingUpdatesCount, + undo, + redo, + canUndo, + canRedo, + } = useMatrix(study.id, url, enableTimeSeriesColumns, enableAggregateColumns); + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + if (isLoading) { + return ; + } + + if (error) { + return ; + } + + if (!data || data.length === 0) { + return ; + } + + return ( + + + {t(title)} + setOpenImportDialog(true)} + onSave={handleSaveUpdates} + studyId={study.id} + path={url} + disabled={data.length === 0} + pendingUpdatesCount={pendingUpdatesCount} + isSubmitting={isSubmitting} + undo={undo} + redo={redo} + canUndo={canUndo} + canRedo={canRedo} + /> + + + + {openImportDialog && ( + setOpenImportDialog(false)} + onImport={handleImport} + accept={{ "text/*": [".csv", ".tsv", ".txt"] }} + /> + )} + + ); +} + +export default Matrix; diff --git a/webapp/src/components/common/MatrixGrid/MatrixActions.tsx b/webapp/src/components/common/MatrixGrid/MatrixActions.tsx new file mode 100644 index 0000000000..46cae239cc --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/MatrixActions.tsx @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { Box, Divider, IconButton, Tooltip } from "@mui/material"; +import SplitButton from "../buttons/SplitButton"; +import FileDownload from "@mui/icons-material/FileDownload"; +import { useTranslation } from "react-i18next"; +import { LoadingButton } from "@mui/lab"; +import Save from "@mui/icons-material/Save"; +import { Undo, Redo } from "@mui/icons-material"; +import DownloadMatrixButton from "../buttons/DownloadMatrixButton"; + +interface MatrixActionsProps { + onImport: VoidFunction; + onSave: VoidFunction; + studyId: string; + path: string; + disabled: boolean; + pendingUpdatesCount: number; + isSubmitting: boolean; + undo: VoidFunction; + redo: VoidFunction; + canUndo: boolean; + canRedo: boolean; +} + +function MatrixActions({ + onImport, + onSave, + studyId, + path, + disabled, + pendingUpdatesCount, + isSubmitting, + undo, + redo, + canUndo, + canRedo, +}: MatrixActionsProps) { + const { t } = useTranslation(); + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + + + + + + + + + + + + + + + + } + variant="contained" + size="small" + disabled={pendingUpdatesCount === 0} + > + ({pendingUpdatesCount}) + + + , + }} + disabled={isSubmitting} + > + {t("global.import")} + + + + ); +} + +export default MatrixActions; diff --git a/webapp/src/components/common/MatrixGrid/index.test.tsx b/webapp/src/components/common/MatrixGrid/index.test.tsx new file mode 100644 index 0000000000..363ae7b8c2 --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/index.test.tsx @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { render } from "@testing-library/react"; +import MatrixGrid, { MatrixGridProps } from "."; +import Box from "@mui/material/Box"; +import { mockGetBoundingClientRect } from "../../../tests/mocks/mockGetBoundingClientRect"; +import { type EnhancedGridColumn, ColumnTypes } from "./types"; +import { mockHTMLCanvasElement } from "../../../tests/mocks/mockHTMLCanvasElement"; + +beforeEach(() => { + mockHTMLCanvasElement(); + mockGetBoundingClientRect(); + vi.clearAllMocks(); +}); + +function renderMatrixGrid( + width: string, + height: string, + data: MatrixGridProps["data"], + columns: EnhancedGridColumn[], + rows: number, +) { + return render( + + + , + ); +} + +function assertDimensions( + element: HTMLElement, + expectedWidth: number, + expectedHeight: number, +) { + const rect = element.getBoundingClientRect(); + expect(rect.width).toBe(expectedWidth); + expect(rect.height).toBe(expectedHeight); +} + +describe("MatrixGrid rendering", () => { + test("MatrixGrid should be rendered within a 450x500px container and match these dimensions", () => { + const data = [ + [1, 2, 3], + [4, 5, 6], + ]; + + const columns = [ + { + id: "col1", + title: "Column 1", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 0, + }, + { + id: "col2", + title: "Column 2", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 1, + }, + { + id: "col3", + title: "Column 3", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 2, + }, + ]; + + const rows = 2; + + // Render the MatrixGrid inside a parent container with specific dimensions + const { container } = renderMatrixGrid( + "450px", // Use inline style for exact measurement + "500px", + data, + columns, + rows, + ); + + const matrix = container.firstChild; + + if (matrix instanceof HTMLElement) { + expect(matrix).toBeInTheDocument(); + assertDimensions(matrix, 450, 500); + } else { + throw new Error("Expected an HTMLElement but received a different node."); + } + }); + + test("MatrixGrid should render correctly with no data", () => { + const data: MatrixGridProps["data"] = []; + + const columns = [ + { + id: "col1", + title: "Column 1", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 0, + }, + { + id: "col2", + title: "Column 2", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 1, + }, + { + id: "col3", + title: "Column 3", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 2, + }, + ]; + + const rows = 0; + + const { container } = renderMatrixGrid( + "450px", + "500px", + data, + columns, + rows, + ); + + const matrix = container.firstChild; + + if (matrix instanceof HTMLElement) { + expect(matrix).toBeInTheDocument(); + assertDimensions(matrix, 450, 500); + } else { + throw new Error("Expected an HTMLElement but received a different node."); + } + }); + + test("MatrixGrid should match the provided dimensions when resized", () => { + const data = [ + [1, 2, 3], + [4, 5, 6], + ]; + + const columns = [ + { + id: "col1", + title: "Column 1", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 0, + }, + { + id: "col2", + title: "Column 2", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 1, + }, + { + id: "col3", + title: "Column 3", + width: 100, + type: ColumnTypes.Number, + editable: true, + order: 2, + }, + ]; + + const rows = 2; + + const { container, rerender } = renderMatrixGrid( + "450px", + "500px", + data, + columns, + rows, + ); + + let matrix = container.firstChild; + + if (matrix instanceof HTMLElement) { + assertDimensions(matrix, 450, 500); + } else { + throw new Error("Expected an HTMLElement but received a different node."); + } + + rerender( + + + , + ); + + matrix = container.firstChild; + + if (matrix instanceof HTMLElement) { + assertDimensions(matrix, 300, 400); + } else { + throw new Error("Expected an HTMLElement but received a different node."); + } + }); +}); diff --git a/webapp/src/components/common/MatrixGrid/index.tsx b/webapp/src/components/common/MatrixGrid/index.tsx new file mode 100644 index 0000000000..d894b8d4ab --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/index.tsx @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import "@glideapps/glide-data-grid/dist/index.css"; +import DataEditor, { + CompactSelection, + EditableGridCell, + EditListItem, + GridCellKind, + GridSelection, + Item, +} from "@glideapps/glide-data-grid"; +import { useGridCellContent } from "./useGridCellContent"; +import { useMemo, useState } from "react"; +import { EnhancedGridColumn, GridUpdate } from "./types"; +import { darkTheme, readOnlyDarkTheme } from "./utils"; +import { useColumnMapping } from "./useColumnMapping"; + +export interface MatrixGridProps { + data: number[][]; + rows: number; + columns: EnhancedGridColumn[]; + dateTime?: string[]; + aggregates?: Record; + rowHeaders?: string[]; + width?: string; + height?: string; + onCellEdit?: (update: GridUpdate) => void; + onMultipleCellsEdit?: (updates: GridUpdate[]) => void; + readOnly?: boolean; +} + +function MatrixGrid({ + data, + rows, + columns, + dateTime, + aggregates, + rowHeaders, + width = "100%", + height = "100%", + onCellEdit, + onMultipleCellsEdit, + readOnly = false, +}: MatrixGridProps) { + const [selection, setSelection] = useState({ + columns: CompactSelection.empty(), + rows: CompactSelection.empty(), + }); + + const { gridToData } = useColumnMapping(columns); + + const theme = useMemo(() => { + if (readOnly) { + return { + ...darkTheme, + ...readOnlyDarkTheme, + }; + } + + return darkTheme; + }, [readOnly]); + + const getCellContent = useGridCellContent( + data, + columns, + gridToData, + dateTime, + aggregates, + rowHeaders, + readOnly, + ); + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleCellEdited = (coordinates: Item, value: EditableGridCell) => { + if (value.kind !== GridCellKind.Number) { + // Invalid numeric value + return; + } + + const dataCoordinates = gridToData(coordinates); + + if (dataCoordinates && onCellEdit) { + onCellEdit({ coordinates: dataCoordinates, value }); + } + }; + + const handleCellsEdited = (newValues: readonly EditListItem[]) => { + const updates = newValues + .map((edit): GridUpdate | null => { + const dataCoordinates = gridToData(edit.location); + + if (edit.value.kind !== GridCellKind.Number || !dataCoordinates) { + return null; + } + + return { + coordinates: dataCoordinates, + value: edit.value, + }; + }) + .filter((update): update is GridUpdate => update !== null); + + if (updates.length === 0) { + // No valid updates + return; + } + + if (onCellEdit && updates.length === 1) { + // If only one cell is edited,`onCellEdit` is called + // we don't need to call `onMultipleCellsEdit` + return; + } + + if (onMultipleCellsEdit) { + onMultipleCellsEdit(updates); + } + + // Return true to prevent calling `onCellEdit` + // for each cell after`onMultipleCellsEdit` is called + return true; + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + <> + +
+ + ); +} + +export default MatrixGrid; diff --git a/webapp/src/components/common/MatrixGrid/style.ts b/webapp/src/components/common/MatrixGrid/style.ts new file mode 100644 index 0000000000..7711a73c8e --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/style.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { Box, styled, Typography } from "@mui/material"; + +export const MatrixContainer = styled(Box)(() => ({ + width: "100%", + height: "100%", + display: "flex", + flexDirection: "column", + alignItems: "center", + overflow: "hidden", +})); + +export const MatrixHeader = styled(Box)(() => ({ + width: "100%", + display: "flex", + flexFlow: "row wrap", + justifyContent: "space-between", + alignItems: "flex-end", +})); + +export const MatrixTitle = styled(Typography)(() => ({ + fontSize: 20, + fontWeight: 400, + lineHeight: 1, +})); diff --git a/webapp/src/components/common/MatrixGrid/types.ts b/webapp/src/components/common/MatrixGrid/types.ts new file mode 100644 index 0000000000..af94b98d97 --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/types.ts @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { + BaseGridColumn, + EditableGridCell, + Item, +} from "@glideapps/glide-data-grid"; + +//////////////////////////////////////////////////////////////// +// Enums +//////////////////////////////////////////////////////////////// + +export const ColumnTypes = { + DateTime: "datetime", + Number: "number", + Text: "text", + Aggregate: "aggregate", +} as const; + +export const Operations = { + ADD: "+", + SUB: "-", + MUL: "*", + DIV: "/", + ABS: "ABS", + EQ: "=", +} as const; + +//////////////////////////////////////////////////////////////// +// Types +//////////////////////////////////////////////////////////////// + +// Derived types +export type ColumnType = (typeof ColumnTypes)[keyof typeof ColumnTypes]; +export type Operation = (typeof Operations)[keyof typeof Operations]; + +export interface EnhancedGridColumn extends BaseGridColumn { + id: string; + width?: number; + type: ColumnType; + editable: boolean; +} +// Represents data coming from the API +export interface MatrixDataDTO { + data: number[][]; + columns: number[]; + index: number[]; +} + +export type Coordinates = [number, number]; + +// Shape of updates provided by Glide Data Grid +export interface GridUpdate { + coordinates: Item; // The cell being updated + value: EditableGridCell; +} + +// Shape of updates to be sent to the API +export interface MatrixUpdate { + operation: Operation; + value: number; +} + +// Shape of multiple updates to be sent to the API +export interface MatrixUpdateDTO { + coordinates: number[][]; // Array of [col, row] pairs + operation: MatrixUpdate; +} + +export type DateIncrementStrategy = ( + date: moment.Moment, + step: number, +) => moment.Moment; diff --git a/webapp/src/components/common/MatrixGrid/useColumnMapping.test.ts b/webapp/src/components/common/MatrixGrid/useColumnMapping.test.ts new file mode 100644 index 0000000000..e88473b9a6 --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/useColumnMapping.test.ts @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { renderHook } from "@testing-library/react"; +import { describe, test, expect } from "vitest"; +import { useColumnMapping } from "./useColumnMapping"; +import { EnhancedGridColumn, ColumnTypes } from "./types"; + +describe("useColumnMapping", () => { + const testColumns: EnhancedGridColumn[] = [ + { + id: "text", + title: "Text", + type: ColumnTypes.Text, + width: 100, + editable: false, + }, + { + id: "date", + title: "Date", + type: ColumnTypes.DateTime, + width: 100, + editable: false, + }, + { + id: "num1", + title: "Number 1", + type: ColumnTypes.Number, + width: 100, + editable: true, + }, + { + id: "num2", + title: "Number 2", + type: ColumnTypes.Number, + width: 100, + editable: true, + }, + { + id: "agg", + title: "Aggregate", + type: ColumnTypes.Aggregate, + width: 100, + editable: false, + }, + ]; + + test("should create gridToData and dataToGrid functions", () => { + const { result } = renderHook(() => useColumnMapping(testColumns)); + expect(result.current.gridToData).toBeDefined(); + expect(result.current.dataToGrid).toBeDefined(); + }); + + describe("gridToData", () => { + test("should return null for non-data columns", () => { + const { result } = renderHook(() => useColumnMapping(testColumns)); + expect(result.current.gridToData([0, 0])).toBeNull(); // Text column + expect(result.current.gridToData([1, 0])).toBeNull(); // DateTime column + expect(result.current.gridToData([4, 0])).toBeNull(); // Aggregate column + }); + + test("should map grid coordinates to data coordinates for data columns", () => { + const { result } = renderHook(() => useColumnMapping(testColumns)); + expect(result.current.gridToData([2, 0])).toEqual([0, 0]); // First Number column + expect(result.current.gridToData([3, 1])).toEqual([1, 1]); // Second Number column + }); + }); + + describe("dataToGrid", () => { + test("should map data coordinates to grid coordinates", () => { + const { result } = renderHook(() => useColumnMapping(testColumns)); + expect(result.current.dataToGrid([0, 0])).toEqual([2, 0]); // First data column + expect(result.current.dataToGrid([1, 1])).toEqual([3, 1]); // Second data column + }); + }); + + test("should handle columns with only non-data types", () => { + const nonDataColumns: EnhancedGridColumn[] = [ + { + id: "text", + title: "Text", + type: ColumnTypes.Text, + width: 100, + editable: false, + }, + { + id: "date", + title: "Date", + type: ColumnTypes.DateTime, + width: 100, + editable: false, + }, + ]; + const { result } = renderHook(() => useColumnMapping(nonDataColumns)); + expect(result.current.gridToData([0, 0])).toBeNull(); + expect(result.current.gridToData([1, 0])).toBeNull(); + expect(result.current.dataToGrid([0, 0])).toEqual([undefined, 0]); // No data columns, so this should return an invalid grid coordinate + }); + + test("should handle columns with only data types", () => { + const dataOnlyColumns: EnhancedGridColumn[] = [ + { + id: "num1", + title: "Number 1", + type: ColumnTypes.Number, + width: 100, + editable: true, + }, + { + id: "num2", + title: "Number 2", + type: ColumnTypes.Number, + width: 100, + editable: true, + }, + ]; + const { result } = renderHook(() => useColumnMapping(dataOnlyColumns)); + expect(result.current.gridToData([0, 0])).toEqual([0, 0]); + expect(result.current.gridToData([1, 1])).toEqual([1, 1]); + expect(result.current.dataToGrid([0, 0])).toEqual([0, 0]); + expect(result.current.dataToGrid([1, 1])).toEqual([1, 1]); + }); + + test("should memoize the result", () => { + const { result, rerender } = renderHook( + (props) => useColumnMapping(props.columns), + { initialProps: { columns: testColumns } }, + ); + const initialResult = result.current; + rerender({ columns: testColumns }); + expect(result.current).toBe(initialResult); + }); +}); diff --git a/webapp/src/components/common/MatrixGrid/useColumnMapping.ts b/webapp/src/components/common/MatrixGrid/useColumnMapping.ts new file mode 100644 index 0000000000..522f93d025 --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/useColumnMapping.ts @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { useMemo } from "react"; +import { Item } from "@glideapps/glide-data-grid"; +import { EnhancedGridColumn, ColumnTypes } from "./types"; + +/** + * A custom hook that provides coordinate mapping functions for a grid with mixed column types. + * + * @description + * This hook addresses a common issue in grid components that display both data and non-data columns: + * the mismatch between grid coordinates (visual position) and data coordinates (position in the data array). + * + * The problem arises when a grid includes non-data columns (e.g., row headers, date/time columns) + * alongside editable data columns. In such cases, the index of a column in the grid doesn't + * directly correspond to its index in the data array. This can lead to issues where: + * 1. The wrong data is displayed in cells. + * 2. Edits are applied to incorrect data points. + * 3. Non-editable columns are mistakenly treated as editable. + * + * This hook solves these issues by providing two mapping functions: + * - gridToData: Converts grid coordinates to data array coordinates. + * - dataToGrid: Converts data array coordinates to grid coordinates. + * + * By using these functions, components can ensure that they're always working with the correct + * coordinates, whether they're displaying data, handling edits, or managing selection. + * + * @param columns - An array of column definitions, including their types. + * + * @returns An object containing two functions: + * - gridToData: (gridCoord: Item) => Item | null + * Converts grid coordinates to data coordinates. Returns null for non-data columns. + * - dataToGrid: (dataCoord: Item) => Item + * Converts data coordinates to grid coordinates. + */ +export function useColumnMapping(columns: EnhancedGridColumn[]) { + return useMemo(() => { + const dataColumnIndices = columns.reduce((acc, col, index) => { + if (col.type === ColumnTypes.Number) { + acc.push(index); + } + return acc; + }, [] as number[]); + + const gridToData = ([col, row]: Item): Item | null => { + const dataColIndex = dataColumnIndices.indexOf(col); + return dataColIndex !== -1 ? [dataColIndex, row] : null; + }; + + const dataToGrid = ([col, row]: Item): Item => [ + dataColumnIndices[col], + row, + ]; + + return { gridToData, dataToGrid }; + }, [columns]); +} diff --git a/webapp/src/components/common/MatrixGrid/useGridCellContent.test.ts b/webapp/src/components/common/MatrixGrid/useGridCellContent.test.ts new file mode 100644 index 0000000000..084a52d429 --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/useGridCellContent.test.ts @@ -0,0 +1,540 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { renderHook } from "@testing-library/react"; +import { useGridCellContent } from "./useGridCellContent"; +import { ColumnTypes, type EnhancedGridColumn } from "./types"; +import { useColumnMapping } from "./useColumnMapping"; + +// Mocking i18next +vi.mock("i18next", () => { + const i18n = { + language: "fr", + use: vi.fn().mockReturnThis(), + init: vi.fn(), + t: vi.fn((key) => key), + changeLanguage: vi.fn((lang) => { + i18n.language = lang; + return Promise.resolve(); + }), + on: vi.fn(), + }; + return { default: i18n }; +}); + +// Mocking react-i18next +vi.mock("react-i18next", async (importOriginal) => { + const actual = await importOriginal(); + return Object.assign({}, actual, { + useTranslation: () => ({ + t: vi.fn((key) => key), + i18n: { + changeLanguage: vi.fn(), + language: "fr", + }, + }), + initReactI18next: { + type: "3rdParty", + init: vi.fn(), + }, + }); +}); + +function renderGridCellContent( + data: number[][], + columns: EnhancedGridColumn[], + dateTime?: string[], + aggregates?: Record, + rowHeaders?: string[], +) { + const { result: mappingResult } = renderHook(() => useColumnMapping(columns)); + const { gridToData } = mappingResult.current; + + const { result } = renderHook(() => + useGridCellContent( + data, + columns, + gridToData, + dateTime, + aggregates, + rowHeaders, + ), + ); + + return result.current; +} + +describe("useGridCellContent", () => { + test("returns correct text cell content for DateTime columns", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "date", + title: "Date", + type: ColumnTypes.DateTime, + width: 150, + editable: false, + }, + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + ]; + + const dateTime = ["2024-01-07T00:00:00Z", "2024-01-02T00:00:00Z"]; + + const data = [ + [11, 10], + [12, 15], + ]; + + const getCellContent = renderGridCellContent(data, columns, dateTime); + const cell = getCellContent([0, 0]); + + if ("displayData" in cell) { + expect(cell.kind).toBe("text"); + expect(cell.displayData).toBe("7 janv. 2024, 00:00"); + } else { + throw new Error("Expected a text cell with displayData"); + } + }); + + describe("returns correct cell content for Aggregate columns", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "total", + title: "Total", + type: ColumnTypes.Aggregate, + width: 100, + editable: false, + }, + ]; + + const data = [ + [10, 20, 30], + [15, 25, 35], + [5, 15, 25], + ]; + + const aggregates = { + total: [60, 75, 45], + }; + + // Tests for each row in the aggregates array + test.each([ + [0, 60], // Row index 0, expected sum 60 + [1, 75], // Row index 1, expected sum 75 + [2, 45], // Row index 2, expected sum 45 + ])( + "ensures the correct numeric cell content is returned for aggregates at row %i", + (row, expectedData) => { + const getCellContent = renderGridCellContent( + data, + columns, + undefined, + aggregates, + ); + + const cell = getCellContent([0, row]); // Column index is 0 because we only have one column of aggregates + + if ("data" in cell) { + expect(cell.kind).toBe("number"); + expect(cell.data).toBe(expectedData); + } else { + throw new Error(`Expected a number cell with data at row [${row}]`); + } + }, + ); + }); + + test("returns correct content for DateTime, Number, and Aggregate columns", () => { + const columns = [ + { + id: "date", + title: "Date", + type: ColumnTypes.DateTime, + width: 150, + editable: false, + }, + { + id: "ts1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + { + id: "ts2", + title: "TS 2", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + { + id: "total", + title: "Total", + type: ColumnTypes.Aggregate, + width: 100, + editable: false, + }, + ]; + + const dateTime = ["2021-01-01T00:00:00Z", "2021-01-02T00:00:00Z"]; + + const data = [ + [100, 200], + [150, 250], + ]; + + const aggregates = { + total: [300, 400], + }; + + const getCellContent = renderGridCellContent( + data, + columns, + dateTime, + aggregates, + ); + + const dateTimeCell = getCellContent([0, 0]); + + if (dateTimeCell.kind === "text" && "displayData" in dateTimeCell) { + expect(dateTimeCell.data).toBe(""); + expect(dateTimeCell.displayData).toBe("1 janv. 2021, 00:00"); + } else { + throw new Error( + "Expected a DateTime cell with displayData containing the year 2021", + ); + } + + const numberCell = getCellContent([1, 0]); + + if (numberCell.kind === "number" && "data" in numberCell) { + expect(numberCell.data).toBe(100); + } else { + throw new Error("Expected a Number cell with data"); + } + + const aggregateCell = getCellContent([3, 0]); + + if (aggregateCell.kind === "number" && "data" in aggregateCell) { + expect(aggregateCell.data).toBe(300); + } else { + throw new Error("Expected an Aggregate cell with data"); + } + }); +}); + +describe("useGridCellContent with mixed column types", () => { + test("handles non-data columns correctly and accesses data columns properly", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "rowHeader", + title: "Row", + type: ColumnTypes.Text, + width: 100, + editable: false, + }, + { + id: "date", + title: "Date", + type: ColumnTypes.DateTime, + width: 150, + editable: false, + }, + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + { + id: "data2", + title: "TS 2", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + { + id: "total", + title: "Total", + type: ColumnTypes.Aggregate, + width: 100, + editable: false, + }, + ]; + + const rowHeaders = ["Row 1", "Row 2"]; + const dateTime = ["2024-01-01T00:00:00Z", "2024-01-02T00:00:00Z"]; + const data = [ + [100, 200], + [150, 250], + ]; + const aggregates = { + total: [300, 400], + }; + + const getCellContent = renderGridCellContent( + data, + columns, + dateTime, + aggregates, + rowHeaders, + ); + + // Test row header (Text column) + const rowHeaderCell = getCellContent([0, 0]); + + if (rowHeaderCell.kind === "text" && "displayData" in rowHeaderCell) { + expect(rowHeaderCell.displayData).toBe("Row 1"); + } else { + throw new Error("Expected a text cell with data for row header"); + } + + // Test date column (DateTime column) + const dateCell = getCellContent([1, 0]); + if (dateCell.kind === "text" && "displayData" in dateCell) { + expect(dateCell.data).toBe(""); + expect(dateCell.displayData).toBe("1 janv. 2024, 00:00"); + } else { + throw new Error("Expected a text cell with data for date"); + } + + // Test first data column (Number column) + const firstDataCell = getCellContent([2, 0]); + + if (firstDataCell.kind === "number" && "data" in firstDataCell) { + expect(firstDataCell.data).toBe(100); + } else { + throw new Error("Expected a number cell with data for first data column"); + } + + // Test second data column (Number column) + const secondDataCell = getCellContent([3, 0]); + + if (secondDataCell.kind === "number" && "data" in secondDataCell) { + expect(secondDataCell.data).toBe(200); + } else { + throw new Error( + "Expected a number cell with data for second data column", + ); + } + + // Test aggregate column + const aggregateCell = getCellContent([4, 0]); + + if (aggregateCell.kind === "number" && "data" in aggregateCell) { + expect(aggregateCell.data).toBe(300); + } else { + throw new Error("Expected a number cell with data for aggregate column"); + } + }); + + test("correctly handles data columns when non-data columns are removed", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + { + id: "data2", + title: "TS 2", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + { + id: "data3", + title: "TS 3", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + ]; + + const data = [ + [100, 200, 300], + [150, 250, 350], + ]; + + const getCellContent = renderGridCellContent(data, columns); + + // Test all data columns + for (let i = 0; i < 3; i++) { + const cell = getCellContent([i, 0]); + if (cell.kind === "number" && "data" in cell) { + expect(cell.data).toBe(data[0][i]); + } else { + throw new Error(`Expected a number cell with data for column ${i}`); + } + } + }); +}); + +describe("useGridCellContent additional tests", () => { + test("handles empty data array correctly", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + ]; + const data: number[][] = []; + + const getCellContent = renderGridCellContent(data, columns); + + const cell = getCellContent([0, 0]); + if (cell.kind === "number" && "data" in cell) { + expect(cell.data).toBeUndefined(); + } else { + throw new Error("Expected a number cell with undefined data"); + } + }); + + test("handles column access out of bounds", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + ]; + const data = [[100]]; + + const getCellContent = renderGridCellContent(data, columns); + + const cell = getCellContent([1, 0]); // Accessing column index 1 which doesn't exist + expect(cell.kind).toBe("text"); + if ("displayData" in cell) { + expect(cell.displayData).toBe("N/A"); + } else { + throw new Error("Expected a text cell with 'N/A' displayData"); + } + }); + + test("handles row access out of bounds", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + ]; + const data = [[100]]; + + const getCellContent = renderGridCellContent(data, columns); + + const cell = getCellContent([0, 1]); // Accessing row index 1 which doesn't exist + if (cell.kind === "number" && "data" in cell) { + expect(cell.data).toBeUndefined(); + } else { + throw new Error("Expected a number cell with undefined data"); + } + }); + + test("handles missing aggregates correctly", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "total", + title: "Total", + type: ColumnTypes.Aggregate, + width: 100, + editable: false, + }, + ]; + const data = [[100]]; + // No aggregates provided + + const getCellContent = renderGridCellContent(data, columns); + + const cell = getCellContent([0, 0]); + if (cell.kind === "number" && "data" in cell) { + expect(cell.data).toBeUndefined(); + } else { + throw new Error( + "Expected a number cell with undefined data for missing aggregate", + ); + } + }); + + test("handles mixed editable and non-editable columns", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + { + id: "data2", + title: "TS 2", + type: ColumnTypes.Number, + width: 50, + editable: false, + }, + ]; + const data = [[100, 200]]; + + const getCellContent = renderGridCellContent(data, columns); + + const editableCell = getCellContent([0, 0]); + const nonEditableCell = getCellContent([1, 0]); + + if (editableCell.kind === "number" && nonEditableCell.kind === "number") { + expect(editableCell.readonly).toBe(false); + expect(nonEditableCell.readonly).toBe(true); + } else { + throw new Error("Expected number cells with correct readonly property"); + } + }); + + test("handles very large numbers correctly", () => { + const columns: EnhancedGridColumn[] = [ + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + width: 50, + editable: true, + }, + ]; + const largeNumber = 1e20; + const data = [[largeNumber]]; + + const getCellContent = renderGridCellContent(data, columns); + + const cell = getCellContent([0, 0]); + if (cell.kind === "number" && "data" in cell) { + expect(cell.data).toBe(largeNumber); + expect(cell.displayData).toBe(largeNumber.toString()); + } else { + throw new Error("Expected a number cell with correct large number data"); + } + }); +}); diff --git a/webapp/src/components/common/MatrixGrid/useGridCellContent.ts b/webapp/src/components/common/MatrixGrid/useGridCellContent.ts new file mode 100644 index 0000000000..ca610950a8 --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/useGridCellContent.ts @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { useCallback, useMemo } from "react"; +import { GridCell, GridCellKind, Item } from "@glideapps/glide-data-grid"; +import { type EnhancedGridColumn, type ColumnType, ColumnTypes } from "./types"; +import { formatDateTime } from "./utils"; + +type CellContentGenerator = ( + row: number, + col: number, + column: EnhancedGridColumn, + data: number[][], + dateTime?: string[], + aggregates?: Record, + rowHeaders?: string[], +) => GridCell; + +/** + * Map of cell content generators for each column type. + * Each generator function creates the appropriate GridCell based on the column type and data. + */ +const cellContentGenerators: Record = { + [ColumnTypes.Text]: ( + row, + col, + column, + data, + dateTime, + aggregates, + rowHeaders, + ) => ({ + kind: GridCellKind.Text, + data: "", // Custom row headers are not editable + displayData: rowHeaders?.[row] ?? "", + readonly: !column.editable, + allowOverlay: false, + }), + [ColumnTypes.DateTime]: (row, col, column, data, dateTime) => ({ + kind: GridCellKind.Text, + data: "", // Date/time columns are not editable + displayData: formatDateTime(dateTime?.[row] ?? ""), + readonly: !column.editable, + allowOverlay: false, + }), + [ColumnTypes.Number]: (row, col, column, data) => { + const value = data?.[row]?.[col]; + + return { + kind: GridCellKind.Number, + data: value, + displayData: value?.toString(), + readonly: !column.editable, + allowOverlay: true, + }; + }, + [ColumnTypes.Aggregate]: (row, col, column, data, dateTime, aggregates) => { + const value = aggregates?.[column.id]?.[row]; + + return { + kind: GridCellKind.Number, + data: value, + displayData: value?.toString() ?? "", + readonly: !column.editable, + allowOverlay: false, + }; + }, +}; + +/** + * Custom hook to generate cell content for the DataEditor grid. + * + * This hook addresses the challenge of mapping different types of data (numbers, dates, text, aggregates) + * to the correct columns in a grid, regardless of the column arrangement. It's especially useful when + * the grid structure is dynamic and may include special columns like row headers or date/time columns + * that are not part of the main data array. + * + * The hook creates a flexible mapping system that: + * 1. Identifies the type of each column (number, text, date, aggregate). + * 2. For number columns, maps their position in the grid to their index in the data array. + * 3. Generates appropriate cell content based on the column type and data source. + * + * This approach allows for a dynamic grid structure where columns can be added, removed, or rearranged + * without needing to modify the underlying data access logic. + * + * @param data - The matrix of numerical data, where each sub-array represents a row. + * @param columns - Array of column configurations. + * @param gridToData - Optional function to map grid cell coordinates to data array indices. + * @param dateTime - Optional array of date-time strings for date columns. + * @param aggregates - Optional object mapping column IDs to arrays of aggregated values. + * @param rowHeaders - Optional array of row header labels. + * @param readOnly - Whether the grid is read-only (default is false). + * @returns A function that accepts a grid item and returns the configured grid cell content. + */ +export function useGridCellContent( + data: number[][], + columns: EnhancedGridColumn[], + gridToData: (cell: Item) => Item | null, + dateTime?: string[], + aggregates?: Record, + rowHeaders?: string[], + readOnly = false, +): (cell: Item) => GridCell { + const columnMap = useMemo(() => { + return new Map(columns.map((column, index) => [index, column])); + }, [columns]); + + const getCellContent = useCallback( + (cell: Item): GridCell => { + const [col, row] = cell; + const column = columnMap.get(col); + + if (!column) { + return { + kind: GridCellKind.Text, + data: "", + displayData: "N/A", + readonly: true, + allowOverlay: false, + }; + } + + const generator = cellContentGenerators[column.type]; + + if (!generator) { + console.error(`No generator found for column type: ${column.type}`); + return { + kind: GridCellKind.Text, + data: "", + displayData: "Error", + readonly: true, + allowOverlay: false, + }; + } + + // Adjust column index for Number type columns (data columns) + // This ensures we access the correct index in the data array, + // accounting for any non-data columns in the grid + let adjustedCol = col; + + if (column.type === ColumnTypes.Number && gridToData) { + // Map grid cell to data array index + const dataCell = gridToData(cell); + + if (dataCell) { + adjustedCol = dataCell[0]; + } + } + + const gridCell = generator( + row, + adjustedCol, + column, + data, + dateTime, + aggregates, + rowHeaders, + ); + + // Prevent updates for read-only grids + if (readOnly) { + return { + ...gridCell, + allowOverlay: false, + }; + } + + return gridCell; + }, + [columnMap, gridToData, data, dateTime, aggregates, rowHeaders, readOnly], + ); + + return getCellContent; +} diff --git a/webapp/src/components/common/MatrixGrid/useMatrix.test.tsx b/webapp/src/components/common/MatrixGrid/useMatrix.test.tsx new file mode 100644 index 0000000000..aad25a253f --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/useMatrix.test.tsx @@ -0,0 +1,302 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { renderHook, act, waitFor } from "@testing-library/react"; +import { vi, describe, expect, beforeEach } from "vitest"; +import { useMatrix } from "./useMatrix"; +import * as apiMatrix from "../../../services/api/matrix"; +import * as apiStudy from "../../../services/api/study"; +import * as rawStudy from "../../../services/api/studies/raw"; +import { + MatrixEditDTO, + MatrixIndex, + Operator, + StudyOutputDownloadLevelDTO, +} from "../../../common/types"; +import { GridUpdate, MatrixDataDTO } from "./types"; +import { GridCellKind } from "@glideapps/glide-data-grid"; + +vi.mock("../../../services/api/matrix"); +vi.mock("../../../services/api/study"); +vi.mock("../../../services/api/studies/raw"); + +describe("useMatrix", () => { + const mockStudyId = "study123"; + const mockUrl = "https://studies/study123/matrix"; + + const mockMatrixData: MatrixDataDTO = { + data: [ + [1, 2], + [3, 4], + ], + columns: [0, 1], + index: [0, 1], + }; + + const mockMatrixIndex: MatrixIndex = { + start_date: "2023-01-01", + steps: 2, + first_week_size: 7, + level: StudyOutputDownloadLevelDTO.DAILY, + }; + + // Helper function to set up the hook and wait for initial loading + const setupHook = async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue(mockMatrixIndex); + + const { result } = renderHook(() => + useMatrix(mockStudyId, mockUrl, true, true), + ); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + return result; + }; + + // Helper function to create a grid update object + const createGridUpdate = ( + row: number, + col: number, + value: number, + ): GridUpdate => ({ + coordinates: [row, col], + value: { + kind: GridCellKind.Number, + data: value, + displayData: value.toString(), + allowOverlay: true, + }, + }); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + test("should fetch matrix data and index on mount", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue(mockMatrixIndex); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + expect(result.current.data).toEqual(mockMatrixData.data); + expect(result.current.columns.length).toBeGreaterThan(0); + expect(result.current.dateTime.length).toBeGreaterThan(0); + }); + + test("should handle cell edit", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue(mockMatrixIndex); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.handleCellEdit(createGridUpdate(0, 1, 5)); + }); + + expect(result.current.data[1][0]).toBe(5); + expect(result.current.pendingUpdatesCount).toBe(1); + }); + + test("should handle multiple cells edit", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue(mockMatrixIndex); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.handleMultipleCellsEdit([ + createGridUpdate(0, 1, 5), + createGridUpdate(1, 0, 6), + ]); + }); + + expect(result.current.data[1][0]).toBe(5); + expect(result.current.data[0][1]).toBe(6); + expect(result.current.pendingUpdatesCount).toBe(2); + }); + + test("should handle save updates", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue(mockMatrixIndex); + vi.mocked(apiMatrix.updateMatrix).mockResolvedValue(undefined); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.handleCellEdit(createGridUpdate(0, 1, 5)); + }); + + await act(async () => { + await result.current.handleSaveUpdates(); + }); + + const expectedEdit: MatrixEditDTO = { + coordinates: [[1, 0]], + operation: { + operation: Operator.EQ, + value: 5, + }, + }; + + expect(apiMatrix.updateMatrix).toHaveBeenCalledWith(mockStudyId, mockUrl, [ + expectedEdit, + ]); + expect(result.current.pendingUpdatesCount).toBe(0); + }); + + test("should handle file import", async () => { + const mockFile = new File([""], "test.csv", { type: "text/csv" }); + vi.mocked(rawStudy.importFile).mockResolvedValue(); + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue(mockMatrixIndex); + + const result = await setupHook(); + + await act(async () => { + await result.current.handleImport(mockFile); + }); + + expect(rawStudy.importFile).toHaveBeenCalledWith({ + file: mockFile, + studyId: mockStudyId, + path: mockUrl, + }); + }); + + describe("Undo and Redo functionality", () => { + test("should have correct initial undo/redo states", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue( + mockMatrixIndex, + ); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + expect(result.current.canUndo).toBe(false); + expect(result.current.canRedo).toBe(false); + }); + + test("should update canUndo and canRedo states correctly after edits", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue( + mockMatrixIndex, + ); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.handleCellEdit(createGridUpdate(0, 1, 5)); + }); + + expect(result.current.canUndo).toBe(true); + expect(result.current.canRedo).toBe(false); + + act(() => { + result.current.undo(); + }); + + expect(result.current.canUndo).toBe(false); + expect(result.current.canRedo).toBe(true); + + act(() => { + result.current.redo(); + }); + + expect(result.current.canUndo).toBe(true); + expect(result.current.canRedo).toBe(false); + }); + + test("should reset redo state after a new edit", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue( + mockMatrixIndex, + ); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.handleCellEdit(createGridUpdate(0, 1, 5)); + }); + + act(() => { + result.current.undo(); + }); + + expect(result.current.canRedo).toBe(true); + + act(() => { + result.current.handleCellEdit(createGridUpdate(1, 0, 6)); + }); + + expect(result.current.canUndo).toBe(true); + expect(result.current.canRedo).toBe(false); + }); + + test("should handle undo to initial state", async () => { + vi.mocked(apiStudy.getStudyData).mockResolvedValue(mockMatrixData); + vi.mocked(apiMatrix.getStudyMatrixIndex).mockResolvedValue( + mockMatrixIndex, + ); + + const result = await setupHook(); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.handleCellEdit(createGridUpdate(0, 1, 5)); + }); + + act(() => { + result.current.undo(); + }); + + expect(result.current.data).toEqual(mockMatrixData.data); + expect(result.current.canUndo).toBe(false); + expect(result.current.canRedo).toBe(true); + }); + }); +}); diff --git a/webapp/src/components/common/MatrixGrid/useMatrix.ts b/webapp/src/components/common/MatrixGrid/useMatrix.ts new file mode 100644 index 0000000000..3332bcfa6e --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/useMatrix.ts @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { useCallback, useEffect, useMemo, useState } from "react"; +import { AxiosError } from "axios"; +import { enqueueSnackbar } from "notistack"; +import { t } from "i18next"; +import { MatrixIndex, Operator } from "../../../common/types"; +import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar"; +import { + getStudyMatrixIndex, + updateMatrix, +} from "../../../services/api/matrix"; +import { getStudyData } from "../../../services/api/study"; +import { + EnhancedGridColumn, + MatrixDataDTO, + ColumnTypes, + GridUpdate, + MatrixUpdateDTO, +} from "./types"; +import { generateDateTime, generateTimeSeriesColumns } from "./utils"; +import useUndo from "use-undo"; +import { GridCellKind } from "@glideapps/glide-data-grid"; +import { importFile } from "../../../services/api/studies/raw"; + +interface DataState { + data: number[][]; + pendingUpdates: MatrixUpdateDTO[]; +} + +export function useMatrix( + studyId: string, + url: string, + enableTimeSeriesColumns: boolean, + enableAggregateColumns: boolean, +) { + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + const [columnCount, setColumnCount] = useState(0); + const [index, setIndex] = useState(undefined); + const [isLoading, setIsLoading] = useState(true); + const [isSubmitting, setIsSubmitting] = useState(false); + const [error, setError] = useState(undefined); + const [{ present: currentState }, { set: setState, undo, redo, canRedo }] = + useUndo({ data: [], pendingUpdates: [] }); + + const fetchMatrix = useCallback(async () => { + setIsLoading(true); + try { + const [matrix, index] = await Promise.all([ + getStudyData(studyId, url), + getStudyMatrixIndex(studyId, url), + ]); + + setState({ data: matrix.data, pendingUpdates: [] }); + setColumnCount(matrix.columns.length); + setIndex(index); + setIsLoading(false); + } catch (error) { + setError(new Error(t("data.error.matrix"))); + enqueueErrorSnackbar(t("data.error.matrix"), error as AxiosError); + } finally { + setIsLoading(false); + } + }, [enqueueErrorSnackbar, setState, studyId, url]); + + useEffect(() => { + fetchMatrix(); + }, [fetchMatrix]); + + const dateTime = useMemo(() => { + return index ? generateDateTime(index) : []; + }, [index]); + + const columns: EnhancedGridColumn[] = useMemo(() => { + if (!currentState.data) { + return []; + } + + const baseColumns = [ + { + id: "date", + title: "Date", + type: ColumnTypes.DateTime, + editable: false, + }, + ]; + + const dataColumns = enableTimeSeriesColumns + ? generateTimeSeriesColumns({ count: columnCount }) + : []; + + const aggregateColumns = enableAggregateColumns + ? [ + { + id: "min", + title: "Min", + type: ColumnTypes.Aggregate, + width: 50, + editable: false, + }, + { + id: "max", + title: "Max", + type: ColumnTypes.Aggregate, + width: 50, + editable: false, + }, + { + id: "avg", + title: "Avg", + type: ColumnTypes.Aggregate, + width: 50, + editable: false, + }, + ] + : []; + + return [...baseColumns, ...dataColumns, ...aggregateColumns]; + }, [ + currentState.data, + enableTimeSeriesColumns, + columnCount, + enableAggregateColumns, + ]); + + // Apply updates to the matrix data and store them in the pending updates list + const applyUpdates = useCallback( + (updates: GridUpdate[]) => { + const updatedData = currentState.data.map((col) => [...col]); + + const newUpdates: MatrixUpdateDTO[] = updates + .map(({ coordinates: [row, col], value }) => { + if (value.kind === GridCellKind.Number && value.data) { + updatedData[col][row] = value.data; + + return { + coordinates: [[col, row]], + operation: { + operation: Operator.EQ, + value: value.data, + }, + }; + } + + return null; + }) + .filter( + (update): update is NonNullable => update !== null, + ); + + setState({ + data: updatedData, + pendingUpdates: [...currentState.pendingUpdates, ...newUpdates], + }); + }, + [currentState, setState], + ); + + const handleCellEdit = function (update: GridUpdate) { + applyUpdates([update]); + }; + + const handleMultipleCellsEdit = function (updates: GridUpdate[]) { + applyUpdates(updates); + }; + + const handleImport = async (file: File) => { + try { + await importFile({ file, studyId, path: url }); + await fetchMatrix(); + } catch (e) { + enqueueErrorSnackbar(t("matrix.error.import"), e as Error); + } + }; + + const handleSaveUpdates = async () => { + if (!currentState.pendingUpdates.length) { + return; + } + + setIsSubmitting(true); + try { + await updateMatrix(studyId, url, currentState.pendingUpdates); + setState({ data: currentState.data, pendingUpdates: [] }); + enqueueSnackbar(t("matrix.success.matrixUpdate"), { + variant: "success", + }); + } catch (error) { + setError(new Error(t("matrix.error.matrixUpdate"))); + enqueueErrorSnackbar(t("matrix.error.matrixUpdate"), error as AxiosError); + } finally { + setIsSubmitting(false); + } + }; + + const handleUndo = useCallback(() => { + undo(); + }, [undo]); + + const handleRedo = useCallback(() => { + redo(); + }, [redo]); + + const canUndoChanges = useMemo( + () => currentState.pendingUpdates.length > 0, + [currentState.pendingUpdates], + ); + + return { + data: currentState.data, + error, + isLoading, + isSubmitting, + columns, + dateTime, + handleCellEdit, + handleMultipleCellsEdit, + handleImport, + handleSaveUpdates, + pendingUpdatesCount: currentState.pendingUpdates.length, + undo: handleUndo, + redo: handleRedo, + canUndo: canUndoChanges, + canRedo, + }; +} diff --git a/webapp/src/components/common/MatrixGrid/utils.test.ts b/webapp/src/components/common/MatrixGrid/utils.test.ts new file mode 100644 index 0000000000..afe4e21c5c --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/utils.test.ts @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { + MatrixIndex, + StudyOutputDownloadLevelDTO, +} from "../../../common/types"; +import { ColumnTypes } from "./types"; +import { generateDateTime, generateTimeSeriesColumns } from "./utils"; + +describe("generateDateTime", () => { + test("generates correct number of dates", () => { + const metadata: MatrixIndex = { + start_date: "2023-01-01T00:00:00Z", + steps: 5, + first_week_size: 7, + level: StudyOutputDownloadLevelDTO.DAILY, + }; + const result = generateDateTime(metadata); + expect(result).toHaveLength(5); + }); + + test.each([ + { + level: "hourly", + start: "2023-01-01T00:00:00Z", + expected: [ + "2023-01-01T00:00:00.000Z", + "2023-01-01T01:00:00.000Z", + "2023-01-01T02:00:00.000Z", + ], + }, + { + level: "daily", + start: "2023-01-01T00:00:00Z", + expected: [ + "2023-01-01T00:00:00.000Z", + "2023-01-02T00:00:00.000Z", + "2023-01-03T00:00:00.000Z", + ], + }, + { + level: "weekly", + start: "2023-01-01T00:00:00Z", + expected: [ + "2023-01-01T00:00:00.000Z", + "2023-01-08T00:00:00.000Z", + "2023-01-15T00:00:00.000Z", + ], + }, + { + level: "monthly", + start: "2023-01-15T00:00:00Z", + expected: [ + "2023-01-15T00:00:00.000Z", + "2023-02-15T00:00:00.000Z", + "2023-03-15T00:00:00.000Z", + ], + }, + { + level: "annual", + start: "2020-02-29T00:00:00Z", + expected: ["2020-02-29T00:00:00.000Z", "2021-02-28T00:00:00.000Z"], + }, + ] as const)( + "generates correct dates for $level level", + ({ level, start, expected }) => { + const metadata: MatrixIndex = { + start_date: start, + steps: expected.length, + first_week_size: 7, + level: level as MatrixIndex["level"], + }; + + const result = generateDateTime(metadata); + + expect(result).toEqual(expected); + }, + ); + + test("handles edge cases", () => { + const metadata: MatrixIndex = { + start_date: "2023-12-31T23:59:59Z", + steps: 2, + first_week_size: 7, + level: StudyOutputDownloadLevelDTO.HOURLY, + }; + const result = generateDateTime(metadata); + expect(result).toEqual([ + "2023-12-31T23:59:59.000Z", + "2024-01-01T00:59:59.000Z", + ]); + }); +}); + +describe("generateTimeSeriesColumns", () => { + test("generates correct number of columns", () => { + const result = generateTimeSeriesColumns({ count: 5 }); + expect(result).toHaveLength(5); + }); + + test("generates columns with default options", () => { + const result = generateTimeSeriesColumns({ count: 3 }); + expect(result).toEqual([ + { + id: "data1", + title: "TS 1", + type: ColumnTypes.Number, + style: "normal", + width: 50, + editable: true, + }, + { + id: "data2", + title: "TS 2", + type: ColumnTypes.Number, + style: "normal", + width: 50, + editable: true, + }, + { + id: "data3", + title: "TS 3", + type: ColumnTypes.Number, + style: "normal", + width: 50, + editable: true, + }, + ]); + }); + + test("generates columns with custom options", () => { + const result = generateTimeSeriesColumns({ + count: 2, + startIndex: 10, + prefix: "Data", + width: 80, + editable: false, + }); + expect(result).toEqual([ + { + id: "data10", + title: "Data 10", + type: ColumnTypes.Number, + style: "normal", + width: 80, + editable: false, + }, + { + id: "data11", + title: "Data 11", + type: ColumnTypes.Number, + style: "normal", + width: 80, + editable: false, + }, + ]); + }); + + test("handles zero count", () => { + const result = generateTimeSeriesColumns({ count: 0 }); + expect(result).toEqual([]); + }); + + test("handles large count", () => { + const result = generateTimeSeriesColumns({ count: 1000 }); + expect(result).toHaveLength(1000); + expect(result[999].id).toBe("data1000"); + expect(result[999].title).toBe("TS 1000"); + }); + + test("maintains consistent type and style", () => { + const result = generateTimeSeriesColumns({ count: 1000 }); + result.forEach((column) => { + expect(column.type).toBe(ColumnTypes.Number); + expect(column.style).toBe("normal"); + }); + }); +}); diff --git a/webapp/src/components/common/MatrixGrid/utils.ts b/webapp/src/components/common/MatrixGrid/utils.ts new file mode 100644 index 0000000000..ed3e1094ee --- /dev/null +++ b/webapp/src/components/common/MatrixGrid/utils.ts @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import moment from "moment"; +import { + DateIncrementStrategy, + EnhancedGridColumn, + ColumnTypes, +} from "./types"; +import { getCurrentLanguage } from "../../../utils/i18nUtils"; +import { Theme } from "@glideapps/glide-data-grid"; +import { MatrixIndex } from "../../../common/types"; + +export const darkTheme: Theme = { + accentColor: "rgba(255, 184, 0, 0.9)", + accentLight: "rgba(255, 184, 0, 0.2)", + accentFg: "#FFFFFF", + textDark: "#FFFFFF", + textMedium: "#C1C3D9", + textLight: "#A1A5B9", + textBubble: "#FFFFFF", + bgIconHeader: "#1E1F2E", + fgIconHeader: "#FFFFFF", + textHeader: "#FFFFFF", + textGroupHeader: "#C1C3D9", + bgCell: "#262737", // main background color + bgCellMedium: "#2E2F42", + bgHeader: "#1E1F2E", + bgHeaderHasFocus: "#2E2F42", + bgHeaderHovered: "#333447", + bgBubble: "#333447", + bgBubbleSelected: "#3C3E57", + bgSearchResult: "#6366F133", + borderColor: "rgba(255, 255, 255, 0.12)", + drilldownBorder: "rgba(255, 255, 255, 0.35)", + linkColor: "#818CF8", + headerFontStyle: "bold 11px", + baseFontStyle: "13px", + fontFamily: "Inter, sans-serif", + editorFontSize: "13px", + lineHeight: 1.5, + textHeaderSelected: "#FFFFFF", + cellHorizontalPadding: 8, + cellVerticalPadding: 5, + headerIconSize: 16, + markerFontStyle: "normal", +}; + +export const readOnlyDarkTheme: Partial = { + bgCell: "#1A1C2A", + bgCellMedium: "#22243A", + textDark: "#A0A0A0", + textMedium: "#808080", + textLight: "#606060", + accentColor: "#4A4C66", + accentLight: "rgba(74, 76, 102, 0.2)", + borderColor: "rgba(255, 255, 255, 0.08)", + drilldownBorder: "rgba(255, 255, 255, 0.2)", +}; + +const dateIncrementStrategies: Record< + MatrixIndex["level"], + DateIncrementStrategy +> = { + hourly: (date, step) => date.clone().add(step, "hours"), + daily: (date, step) => date.clone().add(step, "days"), + weekly: (date, step) => date.clone().add(step, "weeks"), + monthly: (date, step) => date.clone().add(step, "months"), + annual: (date, step) => date.clone().add(step, "years"), +}; + +const dateTimeFormatOptions: Intl.DateTimeFormatOptions = { + year: "numeric", + month: "short", + day: "numeric", + hour: "numeric", + minute: "numeric", + timeZone: "UTC", // Ensures consistent UTC-based time representation +}; + +//////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////// + +/** + * Formats a date and time string using predefined locale and format options. + * + * This function takes a date/time string, creates a Date object from it, + * and then formats it according to the specified options. The formatting + * is done using the French locale as the primary choice, falling back to + * English if French is not available. + * + * Important: This function will always return the time in UTC, regardless + * of the system's local time zone. This behavior is controlled by the + * 'timeZone' option in dateTimeFormatOptions. + * + * @param dateTime - The date/time string to format. This should be an ISO 8601 string (e.g., "2024-01-01T00:00:00Z"). + * @returns The formatted date/time string in the format specified by dateTimeFormatOptions, always in UTC. + * + * @example returns "1 janv. 2024, 00:00" (French locale) + * formatDateTime("2024-01-01T00:00:00Z") + * + * @example returns "Jan 1, 2024, 12:00 AM" (English locale) + * formatDateTime("2024-01-01T00:00:00Z") + */ +export function formatDateTime(dateTime: string): string { + const date = moment.utc(dateTime); + const currentLocale = getCurrentLanguage(); + const locales = [currentLocale, "en-US"]; + + return date.toDate().toLocaleString(locales, dateTimeFormatOptions); +} + +/** + * Generates an array of date-time strings based on the provided time metadata. + * + * This function creates a series of date-time strings, starting from the given start date + * and incrementing based on the specified level (hourly, daily, weekly, monthly, or yearly). + * It uses the Moment.js library for date manipulation and the ISO 8601 format for date-time strings. + * + * @param timeMetadata - The time metadata object. + * @param timeMetadata.start_date - The starting date-time in ISO 8601 format (e.g., "2023-01-01T00:00:00Z"). + * @param timeMetadata.steps - The number of date-time strings to generate. + * @param timeMetadata.level - The increment level for date-time generation. + * + * @returns An array of ISO 8601 formatted date-time strings. + * + * @example + * const result = generateDateTime({ + * start_date: "2023-01-01T00:00:00Z", + * steps: 3, + * level: "daily" + * }); + * + * Returns: [ + * "2023-01-01T00:00:00.000Z", + * "2023-01-02T00:00:00.000Z", + * "2023-01-03T00:00:00.000Z" + * ] + * + * @see {@link MatrixIndex} for the structure of the timeMetadata object. + * @see {@link DateIncrementStrategy} for the date increment strategy type. + */ +export function generateDateTime({ + // eslint-disable-next-line camelcase + start_date, + steps, + level, +}: MatrixIndex): string[] { + const startDate = moment.utc(start_date, "YYYY-MM-DD HH:mm:ss"); + const incrementStrategy = dateIncrementStrategies[level]; + + return Array.from({ length: steps }, (_, i) => + incrementStrategy(startDate, i).toISOString(), + ); +} + +/** + * Generates an array of EnhancedGridColumn objects representing time series data columns. + * + * @param options - The options for generating time series columns. + * @param options.count - The number of time series columns to generate. + * @param [options.startIndex=1] - The starting index for the time series columns (default is 1). + * @param [options.prefix="TS"] - The prefix to use for the column titles (default is "TS"). + * @param [options.width=50] - The width of each column (default is 50). + * @param [options.editable=true] - Whether the columns should be editable (default is true). + * @param [options.style="normal"] - The style of the columns (default is "normal"). + * @returns An array of EnhancedGridColumn objects representing time series data columns. + * + * @example Usage within a column definition array + * const columns = [ + * { id: "rowHeaders", title: "", type: ColumnTypes.Text, ... }, + * { id: "date", title: "Date", type: ColumnTypes.DateTime, ... }, + * ...generateTimeSeriesColumns({ count: 60 }), + * { id: "min", title: "Min", type: ColumnTypes.Aggregate, ... }, + * { id: "max", title: "Max", type: ColumnTypes.Aggregate, ... }, + * { id: "avg", title: "Avg", type: ColumnTypes.Aggregate, ... } + * ]; + */ +export function generateTimeSeriesColumns({ + count, + startIndex = 1, + prefix = "TS", + width = 50, + editable = true, + style = "normal", +}: { + count: number; + startIndex?: number; + prefix?: string; + width?: number; + editable?: boolean; + style?: "normal" | "highlight"; +}): EnhancedGridColumn[] { + return Array.from({ length: count }, (_, index) => ({ + id: `data${startIndex + index}`, + title: `${prefix} ${startIndex + index}`, + type: ColumnTypes.Number, + style: style, + width: width, + editable: editable, + })); +} diff --git a/webapp/src/components/common/MatrixInput/MatrixAssignDialog.tsx b/webapp/src/components/common/MatrixInput/MatrixAssignDialog.tsx index c8553eda09..4ca1978912 100644 --- a/webapp/src/components/common/MatrixInput/MatrixAssignDialog.tsx +++ b/webapp/src/components/common/MatrixInput/MatrixAssignDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, Divider, Typography } from "@mui/material"; import { AxiosError } from "axios"; import { useSnackbar } from "notistack"; @@ -18,7 +32,7 @@ import UsePromiseCond from "../utils/UsePromiseCond"; import SplitView from "../SplitView"; interface Props { - study: StudyMetadata; + studyId: StudyMetadata["id"]; path: string; open: BasicDialogProps["open"]; onClose: VoidFunction; @@ -26,7 +40,7 @@ interface Props { function MatrixAssignDialog(props: Props) { const [t] = useTranslation(); - const { study, path, open, onClose } = props; + const { studyId, path, open, onClose } = props; const [selectedItem, setSelectedItem] = useState(""); const [currentMatrix, setCurrentMatrix] = useState(); const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); @@ -72,7 +86,7 @@ function MatrixAssignDialog(props: Props) { const handleAssignation = async (matrixId: string) => { try { - await appendCommands(study.id, [ + await appendCommands(studyId, [ { action: CommandEnum.REPLACE_MATRIX, args: { diff --git a/webapp/src/components/common/MatrixInput/index.tsx b/webapp/src/components/common/MatrixInput/index.tsx index c48e67d508..62219a43d8 100644 --- a/webapp/src/components/common/MatrixInput/index.tsx +++ b/webapp/src/components/common/MatrixInput/index.tsx @@ -1,16 +1,31 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { useSnackbar } from "notistack"; import { useState } from "react"; import { AxiosError } from "axios"; import { Typography, Box, Divider } from "@mui/material"; import FileDownloadIcon from "@mui/icons-material/FileDownload"; +import GridOffIcon from "@mui/icons-material/GridOff"; import { MatrixEditDTO, MatrixStats, StudyMetadata, } from "../../../common/types"; import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar"; -import { getStudyData, importFile } from "../../../services/api/study"; +import { getStudyData } from "../../../services/api/study"; import usePromiseWithSnackbarError from "../../../hooks/usePromiseWithSnackbarError"; import { editMatrix, getStudyMatrixIndex } from "../../../services/api/matrix"; import { Root, Content, Header } from "./style"; @@ -21,10 +36,11 @@ import ImportDialog from "../dialogs/ImportDialog"; import MatrixAssignDialog from "./MatrixAssignDialog"; import { fetchMatrixFn } from "../../App/Singlestudy/explore/Modelization/Areas/Hydro/utils"; import SplitButton from "../buttons/SplitButton"; -import DownloadMatrixButton from "../DownloadMatrixButton.tsx"; +import DownloadMatrixButton from "../buttons/DownloadMatrixButton.tsx"; +import { importFile } from "../../../services/api/studies/raw/index.ts"; interface Props { - study: StudyMetadata; + study: StudyMetadata | StudyMetadata["id"]; url: string; columnsNames?: string[] | readonly string[]; rowNames?: string[]; @@ -32,6 +48,7 @@ interface Props { computStats: MatrixStats; fetchFn?: fetchMatrixFn; disableEdit?: boolean; + disableImport?: boolean; enablePercentDisplay?: boolean; } @@ -43,7 +60,8 @@ function MatrixInput({ title, computStats, fetchFn, - disableEdit, + disableEdit = false, + disableImport = false, enablePercentDisplay, }: Props) { const { enqueueSnackbar } = useSnackbar(); @@ -51,6 +69,7 @@ function MatrixInput({ const [t] = useTranslation(); const [openImportDialog, setOpenImportDialog] = useState(false); const [openMatrixAsignDialog, setOpenMatrixAsignDialog] = useState(false); + const studyId = typeof study === "string" ? study : study.id; const { data: matrixData, @@ -58,7 +77,7 @@ function MatrixInput({ reload: reloadMatrix, } = usePromiseWithSnackbarError(fetchMatrixData, { errorMessage: t("data.error.matrix"), - deps: [study.id, url, fetchFn], + deps: [studyId, url, fetchFn], }); const { data: matrixIndex } = usePromiseWithSnackbarError( @@ -66,7 +85,7 @@ function MatrixInput({ if (fetchFn) { return matrixData?.index; } - return getStudyMatrixIndex(study.id, url); + return getStudyMatrixIndex(studyId, url); }, { errorMessage: t("matrix.error.failedToretrieveIndex"), @@ -87,8 +106,8 @@ function MatrixInput({ async function fetchMatrixData() { const res = fetchFn - ? await fetchFn(study.id) - : await getStudyData(study.id, url); + ? await fetchFn(studyId) + : await getStudyData(studyId, url); if (typeof res === "string") { const fixed = res .replace(/NaN/g, '"NaN"') @@ -107,7 +126,7 @@ function MatrixInput({ try { if (change.length > 0) { const sanitizedUrl = url.startsWith("/") ? url.substring(1) : url; - await editMatrix(study.id, sanitizedUrl, change); + await editMatrix(studyId, sanitizedUrl, change); enqueueSnackbar(t("matrix.success.matrixUpdate"), { variant: "success", }); @@ -119,7 +138,7 @@ function MatrixInput({ }; const handleImport = async (file: File) => { - await importFile(file, study.id, url); + await importFile({ file, studyId, path: url }); reloadMatrix(); }; @@ -142,27 +161,29 @@ function MatrixInput({ {title || t("xpansion.timeSeries")} - { - if (index === 0) { - setOpenImportDialog(true); - } else { - setOpenMatrixAsignDialog(true); - } - }} - size="small" - ButtonProps={{ - startIcon: , - }} - > - {t("global.import")} - + {!disableImport && ( + { + if (index === 0) { + setOpenImportDialog(true); + } else { + setOpenMatrixAsignDialog(true); + } + }} + size="small" + ButtonProps={{ + startIcon: , + }} + > + {t("global.import")} + + )} @@ -177,13 +198,18 @@ function MatrixInput({ matrixIndex={matrixIndex} columnsNames={columnsNames} rowNames={rowNames} - readOnly={!!disableEdit} + readOnly={disableEdit} onUpdate={handleUpdate} computStats={computStats} isPercentDisplayEnabled={enablePercentDisplay} /> ) : ( - !isLoading && + !isLoading && ( + + ) )} {openImportDialog && ( @@ -198,7 +224,7 @@ function MatrixInput({ )} {openMatrixAsignDialog && ( { diff --git a/webapp/src/components/common/MatrixInput/style.ts b/webapp/src/components/common/MatrixInput/style.ts index 72b77419cb..148f1b191d 100644 --- a/webapp/src/components/common/MatrixInput/style.ts +++ b/webapp/src/components/common/MatrixInput/style.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { styled, Box, Button } from "@mui/material"; export const Root = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/common/PropertiesView.tsx b/webapp/src/components/common/PropertiesView.tsx index 2fc9dbf90d..dc8fb61ab7 100644 --- a/webapp/src/components/common/PropertiesView.tsx +++ b/webapp/src/components/common/PropertiesView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ReactNode } from "react"; import { Box, Button, SxProps, Theme } from "@mui/material"; import SearchFE from "./fieldEditors/SearchFE"; diff --git a/webapp/src/components/common/SelectMulti.tsx b/webapp/src/components/common/SelectMulti.tsx index 5f916bd3f7..29f95fc5d1 100644 --- a/webapp/src/components/common/SelectMulti.tsx +++ b/webapp/src/components/common/SelectMulti.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as React from "react"; import { Box, @@ -13,6 +27,7 @@ import { Theme, } from "@mui/material"; import { GenericInfo } from "../../common/types"; +import { mergeSxProp } from "../../utils/muiUtils"; interface Props { name: string; @@ -65,7 +80,7 @@ function SelectMulti(props: Props) { .join(", "); return ( - + {name} ( - + {axios.isAxiosError(details) ? ( - + - + {details.response?.status} - + {details.response?.data.exception} - - + + {details.response?.data.description} diff --git a/webapp/src/components/common/SplitLayoutView.tsx b/webapp/src/components/common/SplitLayoutView.tsx index 5df41be676..4145a9e13d 100644 --- a/webapp/src/components/common/SplitLayoutView.tsx +++ b/webapp/src/components/common/SplitLayoutView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ReactNode } from "react"; import { Divider, Box, SxProps, Theme } from "@mui/material"; diff --git a/webapp/src/components/common/SplitView/index.tsx b/webapp/src/components/common/SplitView/index.tsx index 19a708ff90..94186aea7d 100644 --- a/webapp/src/components/common/SplitView/index.tsx +++ b/webapp/src/components/common/SplitView/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import React, { useEffect, useState } from "react"; import Split, { SplitProps } from "react-split"; import { Box } from "@mui/material"; @@ -25,9 +39,9 @@ export interface SplitViewProps { * @param props - The component props. * @param props.id - Identifier to uniquely store the sizes of the panes. * @param props.children - Child components to be rendered within the split views. - * @param props.direction - The orientation of the split view ("horizontal" or "vertical"). - * @param props.sizes - Initial sizes of each view in percentages. The array must sum to 100 and match the number of children. - * @param props.gutterSize - The size of the gutter between split views. Defaults to 4. + * @param [props.direction=horizontal] - The orientation of the split view ("horizontal" or "vertical"). + * @param [props.sizes] - Initial sizes of each view in percentages. The array must sum to 100 and match the number of children. + * @param [props.gutterSize=3] - The size of the gutter between split views. * @returns A React component displaying a split layout view with resizable panes. */ function SplitView({ diff --git a/webapp/src/components/common/StarToggle.tsx b/webapp/src/components/common/StarToggle.tsx index 69ad85f751..44698cbf96 100644 --- a/webapp/src/components/common/StarToggle.tsx +++ b/webapp/src/components/common/StarToggle.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Tooltip } from "@mui/material"; import StarPurple500OutlinedIcon from "@mui/icons-material/StarPurple500Outlined"; import StarOutlineOutlinedIcon from "@mui/icons-material/StarOutlineOutlined"; diff --git a/webapp/src/components/common/TableForm/Table.tsx b/webapp/src/components/common/TableForm/Table.tsx index 5e41d8a297..70bfdd5e75 100644 --- a/webapp/src/components/common/TableForm/Table.tsx +++ b/webapp/src/components/common/TableForm/Table.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import HT from "handsontable"; import * as RA from "ramda-adjunct"; import { useMemo } from "react"; diff --git a/webapp/src/components/common/TableForm/index.tsx b/webapp/src/components/common/TableForm/index.tsx index 44fb08ad1e..58bbf4e10f 100644 --- a/webapp/src/components/common/TableForm/index.tsx +++ b/webapp/src/components/common/TableForm/index.tsx @@ -1,9 +1,23 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as RA from "ramda-adjunct"; import HT from "handsontable"; import { startCase } from "lodash"; import * as R from "ramda"; import { Box, type SxProps } from "@mui/material"; -import type { Theme } from "@mui/system"; +import type { Theme } from "@mui/material"; import { useMemo } from "react"; import { DefaultValues } from "react-hook-form"; import type { IdType } from "../../../common/types"; diff --git a/webapp/src/components/common/TableForm/utils.ts b/webapp/src/components/common/TableForm/utils.ts index 79663993c1..ff47af9481 100644 --- a/webapp/src/components/common/TableForm/utils.ts +++ b/webapp/src/components/common/TableForm/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; import * as RA from "ramda-adjunct"; diff --git a/webapp/src/components/common/TableMode.tsx b/webapp/src/components/common/TableMode.tsx index 7d40d5511f..fa309dc01f 100644 --- a/webapp/src/components/common/TableMode.tsx +++ b/webapp/src/components/common/TableMode.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { StudyMetadata } from "../../common/types"; import usePromise from "../../hooks/usePromise"; diff --git a/webapp/src/components/common/TabsView.tsx b/webapp/src/components/common/TabsView.tsx index 5c96248c8d..cfee995bbf 100644 --- a/webapp/src/components/common/TabsView.tsx +++ b/webapp/src/components/common/TabsView.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TabContext, TabList, TabListProps, TabPanel } from "@mui/lab"; import { Box, Tab } from "@mui/material"; import { useState } from "react"; diff --git a/webapp/src/components/common/TextSeparator.tsx b/webapp/src/components/common/TextSeparator.tsx index 635a89d8e8..1348627465 100644 --- a/webapp/src/components/common/TextSeparator.tsx +++ b/webapp/src/components/common/TextSeparator.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { SxProps, Theme, Divider, Typography, Box } from "@mui/material"; interface Props { @@ -31,9 +45,4 @@ function TextSeparator(props: Props) { ); } -TextSeparator.defaultProps = { - rootStyle: undefined, - textStyle: undefined, -}; - export default TextSeparator; diff --git a/webapp/src/components/common/TreeItemEnhanced.tsx b/webapp/src/components/common/TreeItemEnhanced.tsx new file mode 100644 index 0000000000..6b488de6e7 --- /dev/null +++ b/webapp/src/components/common/TreeItemEnhanced.tsx @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { TreeItem, type TreeItemProps } from "@mui/x-tree-view/TreeItem"; +import { mergeSxProp } from "../../utils/muiUtils"; +import * as R from "ramda"; + +export type TreeItemEnhancedProps = TreeItemProps; + +function TreeItemEnhanced({ onClick, sx, ...rest }: TreeItemEnhancedProps) { + const canExpand = rest.children && R.isNotEmpty(rest.children); + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleClick: TreeItemEnhancedProps["onClick"] = (event) => { + const { target } = event; + + // The item is not selected if the click is on the expand/collapse icon + if ( + canExpand && + target instanceof Element && + target.closest(".MuiTreeItem-iconContainer") + ) { + return; + } + + onClick?.(event); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + .MuiTreeItem-content": { + p: 0, + alignItems: "normal", + // Expand/collapse icon + "& > .MuiTreeItem-iconContainer": { + alignItems: "center", + borderTopLeftRadius: "inherit", + borderBottomLeftRadius: "inherit", + "&:hover": { + background: canExpand ? "inherit" : "none", + }, + }, + "& > .MuiTreeItem-label": { + py: 0.5, + }, + }, + }, + sx, + )} + /> + ); +} + +export default TreeItemEnhanced; diff --git a/webapp/src/components/common/buttons/DownloadButton.tsx b/webapp/src/components/common/buttons/DownloadButton.tsx new file mode 100644 index 0000000000..a67cd914e5 --- /dev/null +++ b/webapp/src/components/common/buttons/DownloadButton.tsx @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import FileUploadIcon from "@mui/icons-material/FileUpload"; +import SplitButton, { SplitButtonProps } from "./SplitButton"; +import { useState } from "react"; +import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar"; +import { useTranslation } from "react-i18next"; +import type { PromiseAny } from "../../../utils/tsUtils"; +import { LoadingButton } from "@mui/lab"; +import { toError } from "../../../utils/fnUtils"; + +export type DownloadButtonProps = { + children?: React.ReactNode; + disabled?: boolean; +} & ( + | { + formatOptions: SplitButtonProps["options"]; + onClick?: (format: OptionValue) => PromiseAny | unknown; + } + | { + formatOptions?: undefined; + onClick?: (format?: undefined) => PromiseAny | unknown; + } +); + +function DownloadButton( + props: DownloadButtonProps, +) { + const { t } = useTranslation(); + const { + disabled, + formatOptions, + onClick, + children: label = t("global.export"), + } = props; + const [isDownloading, setIsDownloading] = useState(false); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + + const btnProps = { + variant: "contained", + size: "small", + disabled, + } as const; + + const loadingBtnProps = { + startIcon: , + loadingPosition: "start", + loading: isDownloading, + } as const; + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleDownload = async (format?: OptionValue) => { + setIsDownloading(true); + + try { + if (formatOptions) { + await onClick?.(format!); + } else { + await onClick?.(); + } + } catch (err) { + enqueueErrorSnackbar(t("global.export.error"), toError(err)); + } + + setIsDownloading(false); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return formatOptions ? ( + handleDownload(format)} + ButtonProps={loadingBtnProps} + > + {label} + + ) : ( + handleDownload()} + > + {label} + + ); +} + +export default DownloadButton; diff --git a/webapp/src/components/common/buttons/DownloadMatrixButton.tsx b/webapp/src/components/common/buttons/DownloadMatrixButton.tsx new file mode 100644 index 0000000000..88b4ec2847 --- /dev/null +++ b/webapp/src/components/common/buttons/DownloadMatrixButton.tsx @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { downloadMatrix } from "../../../services/api/studies/raw"; +import { downloadFile } from "../../../utils/fileUtils"; +import { StudyMetadata } from "../../../common/types"; +import { useTranslation } from "react-i18next"; +import DownloadButton from "./DownloadButton"; + +export interface DownloadMatrixButtonProps { + studyId: StudyMetadata["id"]; + path: string; + disabled?: boolean; + label?: string; +} + +const EXPORT_OPTIONS = [ + { label: "TSV", value: "tsv" }, + { label: "Excel", value: "xlsx" }, +] as const; + +type ExportFormat = (typeof EXPORT_OPTIONS)[number]["value"]; + +function DownloadMatrixButton(props: DownloadMatrixButtonProps) { + const { t } = useTranslation(); + const { studyId, path, disabled, label = t("global.export") } = props; + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleDownload = async (format: ExportFormat) => { + if (!path) { + return; + } + + const isExcel = format === "xlsx"; + + const res = await downloadMatrix({ + studyId, + path, + format, + header: isExcel, + index: isExcel, + }); + + return downloadFile( + res, + `matrix_${studyId}_${path.replace("/", "_")}.${format}`, + ); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + + {label} + + ); +} + +export default DownloadMatrixButton; diff --git a/webapp/src/components/common/buttons/SplitButton.tsx b/webapp/src/components/common/buttons/SplitButton.tsx index 684e74f212..52bca20142 100644 --- a/webapp/src/components/common/buttons/SplitButton.tsx +++ b/webapp/src/components/common/buttons/SplitButton.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import Button from "@mui/material/Button"; import ButtonGroup, { ButtonGroupProps } from "@mui/material/ButtonGroup"; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; @@ -33,6 +47,7 @@ export default function SplitButton( onClick, children, ButtonProps: loadingButtonProps, + disabled, ...buttonGroupProps } = props; const [open, setOpen] = useState(false); @@ -95,7 +110,11 @@ export default function SplitButton( return ( <> - + ( diff --git a/webapp/src/components/common/buttons/UploadFileButton.tsx b/webapp/src/components/common/buttons/UploadFileButton.tsx new file mode 100644 index 0000000000..cc16594be0 --- /dev/null +++ b/webapp/src/components/common/buttons/UploadFileButton.tsx @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { LoadingButton } from "@mui/lab"; +import FileDownloadIcon from "@mui/icons-material/FileDownload"; +import { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar"; +import { toError } from "../../../utils/fnUtils"; +import { Accept, useDropzone } from "react-dropzone"; +import { StudyMetadata } from "../../../common/types"; +import { useSnackbar } from "notistack"; +import { importFile } from "../../../services/api/studies/raw"; + +type ValidateResult = boolean | null | undefined; +type Validate = (file: File) => ValidateResult | Promise; + +export interface UploadFileButtonProps { + studyId: StudyMetadata["id"]; + path: string | ((file: File) => string); + children?: React.ReactNode; + accept?: Accept; + disabled?: boolean; + onUploadSuccessful?: (file: File) => void; + validate?: Validate; +} + +function UploadFileButton(props: UploadFileButtonProps) { + const { t } = useTranslation(); + const { + studyId, + path, + accept, + disabled, + onUploadSuccessful, + children: label = t("global.import"), + } = props; + + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + const { enqueueSnackbar } = useSnackbar(); + const [isUploading, setIsUploading] = useState(false); + const { getInputProps, open } = useDropzone({ + onDropAccepted: handleDropAccepted, + accept, + }); + + // Prevent the user from accidentally leaving the page while uploading + useEffect(() => { + if (isUploading) { + const listener = (e: BeforeUnloadEvent) => { + // eslint-disable-next-line no-param-reassign + e.returnValue = t("global.import"); + }; + + window.addEventListener("beforeunload", listener); + + return () => { + window.removeEventListener("beforeunload", listener); + }; + } + }, [isUploading, t]); + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + async function handleDropAccepted(acceptedFiles: File[]) { + setIsUploading(true); + + const fileToUpload = acceptedFiles[0]; + + try { + const isValid = (await props.validate?.(fileToUpload)) ?? true; + + if (!isValid) { + return; + } + + const filePath = typeof path === "function" ? path(fileToUpload) : path; + + await importFile({ + studyId, + path: filePath, + file: fileToUpload, + createMissing: true, + }); + + enqueueSnackbar(t("global.import.success"), { variant: "success" }); + } catch (err) { + enqueueErrorSnackbar(t("global.import.error"), toError(err)); + return; + } finally { + setIsUploading(false); + } + + onUploadSuccessful?.(fileToUpload); + } + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + <> + {/* `open()` no working without the `` in Firefox */} + + } + loadingPosition="start" + loading={isUploading} + disabled={disabled} + > + {label} + + + ); +} + +export default UploadFileButton; diff --git a/webapp/src/components/common/dialogs/BasicDialog.tsx b/webapp/src/components/common/dialogs/BasicDialog.tsx index 196d4b1b9c..467d970b06 100644 --- a/webapp/src/components/common/dialogs/BasicDialog.tsx +++ b/webapp/src/components/common/dialogs/BasicDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Dialog, DialogActions, @@ -13,10 +27,6 @@ import { SvgIconComponent } from "@mui/icons-material"; import * as R from "ramda"; import { mergeSxProp } from "../../../utils/muiUtils"; -/** - * Types - */ - enum Alert { success, error, @@ -34,10 +44,6 @@ export interface BasicDialogProps extends Omit { contentProps?: DialogContentProps; } -/** - * Styled - */ - const AlertBorder = styled("span", { shouldForwardProp: (prop: string) => !prop.startsWith("$"), })<{ $type: AlertValues }>(({ theme, $type }) => ({ @@ -53,10 +59,6 @@ const AlertBorder = styled("span", { ])(Alert[$type]), })); -/** - * Component - */ - function BasicDialog(props: BasicDialogProps) { const { title, @@ -104,12 +106,4 @@ function BasicDialog(props: BasicDialogProps) { ); } -BasicDialog.defaultProps = { - title: null, - titleIcon: null, - actions: null, - alert: false, - contentProps: null, -}; - export default BasicDialog; diff --git a/webapp/src/components/common/dialogs/ConfirmationDialog.tsx b/webapp/src/components/common/dialogs/ConfirmationDialog.tsx index 769fe36a62..df8141906f 100644 --- a/webapp/src/components/common/dialogs/ConfirmationDialog.tsx +++ b/webapp/src/components/common/dialogs/ConfirmationDialog.tsx @@ -1,11 +1,21 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Button } from "@mui/material"; import { useTranslation } from "react-i18next"; import BasicDialog, { BasicDialogProps } from "./BasicDialog"; -/** - * Types - */ - export interface ConfirmationDialogProps extends Omit { cancelButtonText?: string; @@ -14,10 +24,6 @@ export interface ConfirmationDialogProps onCancel: VoidFunction; } -/** - * Component - */ - function ConfirmationDialog(props: ConfirmationDialogProps) { const { cancelButtonText, @@ -64,9 +70,4 @@ function ConfirmationDialog(props: ConfirmationDialogProps) { ); } -ConfirmationDialog.defaultProps = { - cancelButtonText: null, - confirmButtonText: null, -}; - export default ConfirmationDialog; diff --git a/webapp/src/components/common/dialogs/DataViewerDialog/index.tsx b/webapp/src/components/common/dialogs/DataViewerDialog/index.tsx index ca2cd4384e..156cfbe3e2 100644 --- a/webapp/src/components/common/dialogs/DataViewerDialog/index.tsx +++ b/webapp/src/components/common/dialogs/DataViewerDialog/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { Box, IconButton, Tooltip, Typography } from "@mui/material"; import { useSnackbar } from "notistack"; @@ -126,8 +140,4 @@ function DataViewerDialog(props: Props) { ); } -DataViewerDialog.defaultProps = { - isMatrix: false, -}; - export default DataViewerDialog; diff --git a/webapp/src/components/common/dialogs/DataViewerDialog/styles.ts b/webapp/src/components/common/dialogs/DataViewerDialog/styles.ts index 6ed0e5e442..cd499db66a 100644 --- a/webapp/src/components/common/dialogs/DataViewerDialog/styles.ts +++ b/webapp/src/components/common/dialogs/DataViewerDialog/styles.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Button, styled } from "@mui/material"; export const Code = styled(Box)({ diff --git a/webapp/src/components/common/dialogs/DigestDialog.tsx b/webapp/src/components/common/dialogs/DigestDialog.tsx index c735986144..adaed84ce6 100644 --- a/webapp/src/components/common/dialogs/DigestDialog.tsx +++ b/webapp/src/components/common/dialogs/DigestDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Skeleton } from "@mui/material"; import OkDialog, { OkDialogProps } from "./OkDialog"; import EditableMatrix from "../EditableMatrix"; diff --git a/webapp/src/components/common/dialogs/FormDialog.tsx b/webapp/src/components/common/dialogs/FormDialog.tsx index d58f09983a..4980244f5d 100644 --- a/webapp/src/components/common/dialogs/FormDialog.tsx +++ b/webapp/src/components/common/dialogs/FormDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ import { Button } from "@mui/material"; import { useId, useState } from "react"; diff --git a/webapp/src/components/common/dialogs/ImportDialog.tsx b/webapp/src/components/common/dialogs/ImportDialog.tsx index e300015c7e..a16bbf6df6 100644 --- a/webapp/src/components/common/dialogs/ImportDialog.tsx +++ b/webapp/src/components/common/dialogs/ImportDialog.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { Box, Button, LinearProgress, Paper, Typography } from "@mui/material"; import { FileRejection, useDropzone, type Accept } from "react-dropzone"; diff --git a/webapp/src/components/common/dialogs/OkDialog.tsx b/webapp/src/components/common/dialogs/OkDialog.tsx index b40854e5ac..c8245eb533 100644 --- a/webapp/src/components/common/dialogs/OkDialog.tsx +++ b/webapp/src/components/common/dialogs/OkDialog.tsx @@ -1,21 +1,27 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Button, ButtonProps } from "@mui/material"; import { useTranslation } from "react-i18next"; import BasicDialog, { BasicDialogProps } from "./BasicDialog"; -/** - * Types - */ - export interface OkDialogProps extends Omit { okButtonText?: string; okButtonProps?: Omit; onOk: VoidFunction; } -/** - * Component - */ - function OkDialog(props: OkDialogProps) { const { okButtonText, okButtonProps, onOk, onClose, ...basicDialogProps } = props; @@ -49,9 +55,4 @@ function OkDialog(props: OkDialogProps) { ); } -OkDialog.defaultProps = { - okButtonText: null, - okButtonProps: null, -}; - export default OkDialog; diff --git a/webapp/src/components/common/fieldEditors/BooleanFE.tsx b/webapp/src/components/common/fieldEditors/BooleanFE.tsx index 08ecb5dcb3..56846ead2a 100644 --- a/webapp/src/components/common/fieldEditors/BooleanFE.tsx +++ b/webapp/src/components/common/fieldEditors/BooleanFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { SelectProps } from "@mui/material"; import * as RA from "ramda-adjunct"; import reactHookFormSupport from "../../../hoc/reactHookFormSupport"; diff --git a/webapp/src/components/common/fieldEditors/CheckBoxFE.tsx b/webapp/src/components/common/fieldEditors/CheckBoxFE.tsx index 6e15d7c116..a104d50692 100644 --- a/webapp/src/components/common/fieldEditors/CheckBoxFE.tsx +++ b/webapp/src/components/common/fieldEditors/CheckBoxFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Checkbox, CheckboxProps, diff --git a/webapp/src/components/common/fieldEditors/CheckboxesTagsFE.tsx b/webapp/src/components/common/fieldEditors/CheckboxesTagsFE.tsx index 42e3a7e3fb..1b2b8f9326 100644 --- a/webapp/src/components/common/fieldEditors/CheckboxesTagsFE.tsx +++ b/webapp/src/components/common/fieldEditors/CheckboxesTagsFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Autocomplete, AutocompleteProps, diff --git a/webapp/src/components/common/fieldEditors/ColorPickerFE/index.tsx b/webapp/src/components/common/fieldEditors/ColorPickerFE/index.tsx index e0d39b342e..54bc1bc754 100644 --- a/webapp/src/components/common/fieldEditors/ColorPickerFE/index.tsx +++ b/webapp/src/components/common/fieldEditors/ColorPickerFE/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, TextField, TextFieldProps, InputAdornment } from "@mui/material"; import { ChangeEvent, useRef, useState } from "react"; import { ColorResult, SketchPicker } from "react-color"; diff --git a/webapp/src/components/common/fieldEditors/ColorPickerFE/utils.ts b/webapp/src/components/common/fieldEditors/ColorPickerFE/utils.ts index a42276f7f4..8508a629cd 100644 --- a/webapp/src/components/common/fieldEditors/ColorPickerFE/utils.ts +++ b/webapp/src/components/common/fieldEditors/ColorPickerFE/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ColorResult } from "react-color"; export function stringToRGB(color: string): ColorResult["rgb"] | undefined { diff --git a/webapp/src/components/common/fieldEditors/ListFE/index.tsx b/webapp/src/components/common/fieldEditors/ListFE/index.tsx index 29f3518e26..94082376a5 100644 --- a/webapp/src/components/common/fieldEditors/ListFE/index.tsx +++ b/webapp/src/components/common/fieldEditors/ListFE/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Autocomplete, Box, diff --git a/webapp/src/components/common/fieldEditors/ListFE/utils.ts b/webapp/src/components/common/fieldEditors/ListFE/utils.ts index fd5591a30d..0496f1f066 100644 --- a/webapp/src/components/common/fieldEditors/ListFE/utils.ts +++ b/webapp/src/components/common/fieldEditors/ListFE/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { v4 as uuidv4 } from "uuid"; import * as RA from "ramda-adjunct"; diff --git a/webapp/src/components/common/fieldEditors/NumberFE.tsx b/webapp/src/components/common/fieldEditors/NumberFE.tsx index eb1de8ea53..40947322c1 100644 --- a/webapp/src/components/common/fieldEditors/NumberFE.tsx +++ b/webapp/src/components/common/fieldEditors/NumberFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TextField, TextFieldProps } from "@mui/material"; import * as RA from "ramda-adjunct"; import reactHookFormSupport from "../../../hoc/reactHookFormSupport"; diff --git a/webapp/src/components/common/fieldEditors/PasswordFE.tsx b/webapp/src/components/common/fieldEditors/PasswordFE.tsx index 4a0d1447cf..7723ab0366 100644 --- a/webapp/src/components/common/fieldEditors/PasswordFE.tsx +++ b/webapp/src/components/common/fieldEditors/PasswordFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TextField, TextFieldProps } from "@mui/material"; import reactHookFormSupport from "../../../hoc/reactHookFormSupport"; diff --git a/webapp/src/components/common/fieldEditors/RadioFE.tsx b/webapp/src/components/common/fieldEditors/RadioFE.tsx index ae296f64f3..2b8fa016c4 100644 --- a/webapp/src/components/common/fieldEditors/RadioFE.tsx +++ b/webapp/src/components/common/fieldEditors/RadioFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { FormControl, FormControlLabel, diff --git a/webapp/src/components/common/fieldEditors/SearchFE.tsx b/webapp/src/components/common/fieldEditors/SearchFE.tsx index e9d76c96da..39b1e1d626 100644 --- a/webapp/src/components/common/fieldEditors/SearchFE.tsx +++ b/webapp/src/components/common/fieldEditors/SearchFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { IconButton, InputAdornment } from "@mui/material"; import SearchIcon from "@mui/icons-material/Search"; import ClearIcon from "@mui/icons-material/Clear"; diff --git a/webapp/src/components/common/fieldEditors/SelectFE.tsx b/webapp/src/components/common/fieldEditors/SelectFE.tsx index 938f94f499..56ce7c30b4 100644 --- a/webapp/src/components/common/fieldEditors/SelectFE.tsx +++ b/webapp/src/components/common/fieldEditors/SelectFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { FormControl, FormHelperText, diff --git a/webapp/src/components/common/fieldEditors/StringFE.tsx b/webapp/src/components/common/fieldEditors/StringFE.tsx index a915a40289..1f60a0f5ee 100644 --- a/webapp/src/components/common/fieldEditors/StringFE.tsx +++ b/webapp/src/components/common/fieldEditors/StringFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TextField, TextFieldProps } from "@mui/material"; import reactHookFormSupport from "../../../hoc/reactHookFormSupport"; diff --git a/webapp/src/components/common/fieldEditors/SwitchFE.tsx b/webapp/src/components/common/fieldEditors/SwitchFE.tsx index 4abed57c0c..30d3edd60f 100644 --- a/webapp/src/components/common/fieldEditors/SwitchFE.tsx +++ b/webapp/src/components/common/fieldEditors/SwitchFE.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { FormControl, FormControlLabel, diff --git a/webapp/src/components/common/loaders/AppLoader.tsx b/webapp/src/components/common/loaders/AppLoader.tsx index 57230f7e2f..b8ab955ff3 100644 --- a/webapp/src/components/common/loaders/AppLoader.tsx +++ b/webapp/src/components/common/loaders/AppLoader.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Box, Typography } from "@mui/material"; diff --git a/webapp/src/components/common/loaders/BackdropLoading.tsx b/webapp/src/components/common/loaders/BackdropLoading.tsx index 57ebdcd1d7..29218a2c4e 100644 --- a/webapp/src/components/common/loaders/BackdropLoading.tsx +++ b/webapp/src/components/common/loaders/BackdropLoading.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Backdrop, Box, CircularProgress } from "@mui/material"; interface BackdropLoadingProps { diff --git a/webapp/src/components/common/loaders/GlobalPageLoadingError.tsx b/webapp/src/components/common/loaders/GlobalPageLoadingError.tsx index a595345bcb..f31dc03b1d 100644 --- a/webapp/src/components/common/loaders/GlobalPageLoadingError.tsx +++ b/webapp/src/components/common/loaders/GlobalPageLoadingError.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Box, Typography } from "@mui/material"; import topRightBackground from "../../../assets/img/top-right-background.png"; diff --git a/webapp/src/components/common/loaders/SimpleLoader.tsx b/webapp/src/components/common/loaders/SimpleLoader.tsx index e1785cc000..94efbf71c2 100644 --- a/webapp/src/components/common/loaders/SimpleLoader.tsx +++ b/webapp/src/components/common/loaders/SimpleLoader.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import { Box, CircularProgress } from "@mui/material"; @@ -9,7 +23,7 @@ interface PropTypes { function SimpleLoader(props: PropTypes) { const [t] = useTranslation(); - const { progress, message, color } = props; + const { progress, message, color = "rgba(0,0,0,0)" } = props; return ( ) { const { header, hideHeaderDivider, children } = props; @@ -30,9 +36,4 @@ function BasicPage(props: PropsWithChildren) { ); } -BasicPage.defaultProps = { - header: null, - hideHeaderDivider: false, -}; - export default BasicPage; diff --git a/webapp/src/components/common/page/RootPage.tsx b/webapp/src/components/common/page/RootPage.tsx index a06d1b6e18..7d759a6321 100644 --- a/webapp/src/components/common/page/RootPage.tsx +++ b/webapp/src/components/common/page/RootPage.tsx @@ -1,11 +1,21 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { SvgIconComponent } from "@mui/icons-material"; import { Box, Typography } from "@mui/material"; import BasicPage from "./BasicPage"; -/** - * Types - */ - interface Props { title: string; titleIcon?: SvgIconComponent; @@ -15,10 +25,6 @@ interface Props { children?: React.ReactNode; } -/** - * Component - */ - function RootPage(props: Props) { const { title, @@ -82,11 +88,4 @@ function RootPage(props: Props) { ); } -RootPage.defaultProps = { - titleIcon: null, - headerTopRight: null, - headerBottom: null, - hideHeaderDivider: false, -}; - export default RootPage; diff --git a/webapp/src/components/common/page/SimpleContent.tsx b/webapp/src/components/common/page/SimpleContent.tsx index 6be0cd51b0..cd4804272c 100644 --- a/webapp/src/components/common/page/SimpleContent.tsx +++ b/webapp/src/components/common/page/SimpleContent.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useTranslation } from "react-i18next"; import LiveHelpRoundedIcon from "@mui/icons-material/LiveHelpRounded"; import { Box } from "@mui/material"; @@ -16,6 +30,7 @@ function EmptyView(props: EmptyViewProps) { (value: T): React.MutableRefObject { diff --git a/webapp/src/hooks/useBlocker.ts b/webapp/src/hooks/useBlocker.ts index b942611443..e4fce66307 100644 --- a/webapp/src/hooks/useBlocker.ts +++ b/webapp/src/hooks/useBlocker.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { History, Transition } from "history"; import { useContext, useEffect } from "react"; import { UNSAFE_NavigationContext as NavigationContext } from "react-router-dom"; diff --git a/webapp/src/hooks/useConfirm.ts b/webapp/src/hooks/useConfirm.ts new file mode 100644 index 0000000000..4df7890c7f --- /dev/null +++ b/webapp/src/hooks/useConfirm.ts @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import { useCallback, useRef, useState } from "react"; +import useAutoUpdateRef from "./useAutoUpdateRef"; + +function errorFunction() { + throw new Error("Promise is not pending."); +} + +/** + * Hook that allows to wait for a confirmation from the user with a `Promise`. + * It is intended to be used in conjunction with a confirm view (like `ConfirmationDialog`). + + * @returns An object with the following properties: + * - `showConfirm`: A function that returns a `Promise` that resolves to `true` if the user confirms, + * `false` if the user refuses, and `null` if the user cancel. + * - `isPending`: A boolean that indicates if the promise is pending. + * - `yes`: A function that resolves the promise with `true`. + * - `no`: A function that resolves the promise with `false`. + * - `cancel`: A function that resolves the promise with `null`. + */ +function useConfirm() { + const [isPending, setIsPending] = useState(false); + const isPendingRef = useAutoUpdateRef(isPending); + const yesRef = useRef(errorFunction); + const noRef = useRef(errorFunction); + const cancelRef = useRef(errorFunction); + + const showConfirm = useCallback(() => { + if (isPendingRef.current) { + throw new Error("A promise is already pending"); + } + + setIsPending(true); + + return new Promise((resolve, reject) => { + yesRef.current = () => { + resolve(true); + setIsPending(false); + }; + + noRef.current = () => { + resolve(false); + setIsPending(false); + }; + + cancelRef.current = () => { + resolve(null); + setIsPending(false); + }; + }); + }, []); + + return { + showConfirm, + isPending, + yes: yesRef.current, + no: noRef.current, + cancel: cancelRef.current, + }; +} + +export default useConfirm; diff --git a/webapp/src/hooks/useDebounce.ts b/webapp/src/hooks/useDebounce.ts index b854f42d30..231c4849a2 100644 --- a/webapp/src/hooks/useDebounce.ts +++ b/webapp/src/hooks/useDebounce.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { debounce, DebouncedFunc, diff --git a/webapp/src/hooks/useDebouncedEffect.ts b/webapp/src/hooks/useDebouncedEffect.ts index a4850c9531..90fdbdeb3d 100644 --- a/webapp/src/hooks/useDebouncedEffect.ts +++ b/webapp/src/hooks/useDebouncedEffect.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; import * as RA from "ramda-adjunct"; import { useEffect } from "react"; diff --git a/webapp/src/hooks/useDebouncedState.ts b/webapp/src/hooks/useDebouncedState.ts index 7a3dd7cb15..470248a02d 100644 --- a/webapp/src/hooks/useDebouncedState.ts +++ b/webapp/src/hooks/useDebouncedState.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DebouncedFunc, DebouncedFuncLeading, diff --git a/webapp/src/hooks/useEnqueueErrorSnackbar.tsx b/webapp/src/hooks/useEnqueueErrorSnackbar.tsx index 7108492f9e..5b04adb42b 100644 --- a/webapp/src/hooks/useEnqueueErrorSnackbar.tsx +++ b/webapp/src/hooks/useEnqueueErrorSnackbar.tsx @@ -1,12 +1,22 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { ProviderContext, useSnackbar } from "notistack"; import { useCallback } from "react"; import { L } from "ts-toolbelt"; import SnackErrorMessage from "../components/common/SnackErrorMessage"; -/** - * Types - */ - type EnqueueErrorType = ProviderContext["enqueueSnackbar"]; type EnqueueErrorSnackbarType = ( @@ -14,10 +24,6 @@ type EnqueueErrorSnackbarType = ( details: string | Error, ) => ReturnType; -/** - * Hook - */ - function useEnqueueErrorSnackbar(): EnqueueErrorSnackbarType { const { enqueueSnackbar } = useSnackbar(); diff --git a/webapp/src/hooks/useMemoLocked.ts b/webapp/src/hooks/useMemoLocked.ts index b6e03535f9..1d536c92a7 100644 --- a/webapp/src/hooks/useMemoLocked.ts +++ b/webapp/src/hooks/useMemoLocked.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; /* diff --git a/webapp/src/hooks/useNavigateOnCondition.ts b/webapp/src/hooks/useNavigateOnCondition.ts index 036ce0e72f..3608856916 100644 --- a/webapp/src/hooks/useNavigateOnCondition.ts +++ b/webapp/src/hooks/useNavigateOnCondition.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DependencyList } from "react"; import { useNavigate, To } from "react-router-dom"; import { useUpdateEffect } from "react-use"; diff --git a/webapp/src/hooks/useOperationInProgressCount.ts b/webapp/src/hooks/useOperationInProgressCount.ts index bc71fb677a..26be81248b 100644 --- a/webapp/src/hooks/useOperationInProgressCount.ts +++ b/webapp/src/hooks/useOperationInProgressCount.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useMemo, useState } from "react"; import * as R from "ramda"; diff --git a/webapp/src/hooks/usePromise.ts b/webapp/src/hooks/usePromise.ts index 890874e4fa..8769a05128 100644 --- a/webapp/src/hooks/usePromise.ts +++ b/webapp/src/hooks/usePromise.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useCallback, useEffect, useState } from "react"; import { usePromise as usePromiseWrapper } from "react-use"; import { isDependencyList } from "../utils/reactUtils"; diff --git a/webapp/src/hooks/usePromiseWithSnackbarError.ts b/webapp/src/hooks/usePromiseWithSnackbarError.ts index e8e9ba0e17..346d7568a6 100644 --- a/webapp/src/hooks/usePromiseWithSnackbarError.ts +++ b/webapp/src/hooks/usePromiseWithSnackbarError.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect } from "react"; import useEnqueueErrorSnackbar from "./useEnqueueErrorSnackbar"; import usePromise, { UsePromiseResponse, UsePromiseParams } from "./usePromise"; diff --git a/webapp/src/hooks/usePrompt.ts b/webapp/src/hooks/usePrompt.ts index 460e0bcb0d..6f0d1d0d76 100644 --- a/webapp/src/hooks/usePrompt.ts +++ b/webapp/src/hooks/usePrompt.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import useBlocker from "./useBlocker"; // * Workaround until it will be supported by react-router v6. diff --git a/webapp/src/hooks/useUpdateEffectOnce.ts b/webapp/src/hooks/useUpdateEffectOnce.ts index 61fedd115e..c8ec4d7808 100644 --- a/webapp/src/hooks/useUpdateEffectOnce.ts +++ b/webapp/src/hooks/useUpdateEffectOnce.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useEffect, useRef } from "react"; import { useUpdateEffect } from "react-use"; diff --git a/webapp/src/i18n.ts b/webapp/src/i18n.ts index 980cffbf89..f2f144fe87 100644 --- a/webapp/src/i18n.ts +++ b/webapp/src/i18n.ts @@ -1,8 +1,21 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import i18n from "i18next"; import Backend from "i18next-http-backend"; import LanguageDetector from "i18next-browser-languagedetector"; import { initReactI18next } from "react-i18next"; -import { version } from "../package.json"; i18n // load translation using xhr -> see /public/locales @@ -20,7 +33,7 @@ i18n backend: { loadPath: `${ import.meta.env.BASE_URL - }locales/{{lng}}/{{ns}}.json?v=${version}`, + }locales/{{lng}}/{{ns}}.json?id=${__BUILD_TIMESTAMP__}`, }, react: { useSuspense: false, diff --git a/webapp/src/index.test.tsx b/webapp/src/index.test.tsx index 6317806c00..e2c5ffa601 100644 --- a/webapp/src/index.test.tsx +++ b/webapp/src/index.test.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { render } from "@testing-library/react"; import { Provider } from "react-redux"; import { StyledEngineProvider } from "@mui/material"; diff --git a/webapp/src/index.tsx b/webapp/src/index.tsx index 2c6792f7a8..4a3d8d1d42 100644 --- a/webapp/src/index.tsx +++ b/webapp/src/index.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createRoot } from "react-dom/client"; import { Provider } from "react-redux"; import { StyledEngineProvider } from "@mui/material"; diff --git a/webapp/src/redux/components/UseAsyncAppSelectorCond.tsx b/webapp/src/redux/components/UseAsyncAppSelectorCond.tsx index 7244b74c37..9e62e3bddd 100644 --- a/webapp/src/redux/components/UseAsyncAppSelectorCond.tsx +++ b/webapp/src/redux/components/UseAsyncAppSelectorCond.tsx @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as R from "ramda"; import { UseAsyncEntityStateResponse } from "../hooks/useAsyncAppSelector"; import { FetchStatus } from "../utils"; diff --git a/webapp/src/redux/ducks/auth.ts b/webapp/src/redux/ducks/auth.ts index f2eadef4d2..308b802827 100644 --- a/webapp/src/redux/ducks/auth.ts +++ b/webapp/src/redux/ducks/auth.ts @@ -1,5 +1,19 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAsyncThunk, createReducer, isAnyOf } from "@reduxjs/toolkit"; -import jwtDecode, { JwtPayload } from "jwt-decode"; +import { jwtDecode, type JwtPayload } from "jwt-decode"; import { UserInfo } from "../../common/types"; import * as authApi from "../../services/api/auth"; import * as clientApi from "../../services/api/client"; diff --git a/webapp/src/redux/ducks/groups.ts b/webapp/src/redux/ducks/groups.ts index 08e932a4d6..0d487f3a35 100644 --- a/webapp/src/redux/ducks/groups.ts +++ b/webapp/src/redux/ducks/groups.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAsyncThunk, createEntityAdapter, diff --git a/webapp/src/redux/ducks/index.ts b/webapp/src/redux/ducks/index.ts index cbe18b24f7..7fe58f0a35 100644 --- a/webapp/src/redux/ducks/index.ts +++ b/webapp/src/redux/ducks/index.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { Action, combineReducers } from "redux"; import { L } from "ts-toolbelt"; import studies from "./studies"; diff --git a/webapp/src/redux/ducks/studies.ts b/webapp/src/redux/ducks/studies.ts index 2a52eda706..6260a002f0 100644 --- a/webapp/src/redux/ducks/studies.ts +++ b/webapp/src/redux/ducks/studies.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAction, createAsyncThunk, diff --git a/webapp/src/redux/ducks/studyMaps.ts b/webapp/src/redux/ducks/studyMaps.ts index 3075e0dbff..9b5d1303dd 100644 --- a/webapp/src/redux/ducks/studyMaps.ts +++ b/webapp/src/redux/ducks/studyMaps.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAction, createAsyncThunk, diff --git a/webapp/src/redux/ducks/studySyntheses.ts b/webapp/src/redux/ducks/studySyntheses.ts index a7ae6cdc52..00beb748b4 100644 --- a/webapp/src/redux/ducks/studySyntheses.ts +++ b/webapp/src/redux/ducks/studySyntheses.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAction, createAsyncThunk, diff --git a/webapp/src/redux/ducks/ui.ts b/webapp/src/redux/ducks/ui.ts index 85b428c858..18d4886b55 100644 --- a/webapp/src/redux/ducks/ui.ts +++ b/webapp/src/redux/ducks/ui.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAction, createReducer } from "@reduxjs/toolkit"; import { makeActionName } from "../utils"; diff --git a/webapp/src/redux/ducks/users.ts b/webapp/src/redux/ducks/users.ts index 1ad9f7e124..89922f8018 100644 --- a/webapp/src/redux/ducks/users.ts +++ b/webapp/src/redux/ducks/users.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAsyncThunk, createEntityAdapter, diff --git a/webapp/src/redux/hooks/useAppDispatch.ts b/webapp/src/redux/hooks/useAppDispatch.ts index 6c73d110fa..62c5305391 100644 --- a/webapp/src/redux/hooks/useAppDispatch.ts +++ b/webapp/src/redux/hooks/useAppDispatch.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useDispatch } from "react-redux"; import { AppDispatch } from "../store"; diff --git a/webapp/src/redux/hooks/useAppSelector.ts b/webapp/src/redux/hooks/useAppSelector.ts index 8b0bcb08b0..54a95cf219 100644 --- a/webapp/src/redux/hooks/useAppSelector.ts +++ b/webapp/src/redux/hooks/useAppSelector.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TypedUseSelectorHook, useSelector } from "react-redux"; import { AppState } from "../ducks"; diff --git a/webapp/src/redux/hooks/useAsyncAppSelector.ts b/webapp/src/redux/hooks/useAsyncAppSelector.ts index 831cb294a1..2d01ab895a 100644 --- a/webapp/src/redux/hooks/useAsyncAppSelector.ts +++ b/webapp/src/redux/hooks/useAsyncAppSelector.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AsyncThunk } from "@reduxjs/toolkit"; import { useEffect } from "react"; import { AppState } from "../ducks"; diff --git a/webapp/src/redux/hooks/useStudyMaps.ts b/webapp/src/redux/hooks/useStudyMaps.ts index 0057ee95e0..5e187fed1f 100644 --- a/webapp/src/redux/hooks/useStudyMaps.ts +++ b/webapp/src/redux/hooks/useStudyMaps.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { StudyMetadata } from "../../common/types"; import { AppState } from "../ducks"; diff --git a/webapp/src/redux/hooks/useStudySynthesis.ts b/webapp/src/redux/hooks/useStudySynthesis.ts index 0dcf068c6b..57fdf75931 100644 --- a/webapp/src/redux/hooks/useStudySynthesis.ts +++ b/webapp/src/redux/hooks/useStudySynthesis.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { useState } from "react"; import { useAsync } from "react-use"; import { StudyMetadata } from "../../common/types"; diff --git a/webapp/src/redux/middlewares/localStorageMiddleware.ts b/webapp/src/redux/middlewares/localStorageMiddleware.ts index 2cd2a288e9..2e0e4baded 100644 --- a/webapp/src/redux/middlewares/localStorageMiddleware.ts +++ b/webapp/src/redux/middlewares/localStorageMiddleware.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createListenerMiddleware, isAnyOf } from "@reduxjs/toolkit"; import { UserInfo } from "../../common/types"; import storage, { StorageKey } from "../../services/utils/localStorage"; diff --git a/webapp/src/redux/selectors.ts b/webapp/src/redux/selectors.ts index 61c0c71f59..5fb8947726 100644 --- a/webapp/src/redux/selectors.ts +++ b/webapp/src/redux/selectors.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createEntityAdapter, createSelector } from "@reduxjs/toolkit"; import { last } from "ramda"; import { diff --git a/webapp/src/redux/store.ts b/webapp/src/redux/store.ts index 0fc727390b..35c9296570 100644 --- a/webapp/src/redux/store.ts +++ b/webapp/src/redux/store.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { configureStore } from "@reduxjs/toolkit"; import { ThunkAction } from "redux-thunk"; import { AnyAction } from "redux"; diff --git a/webapp/src/redux/utils.ts b/webapp/src/redux/utils.ts index 66f2c890f8..ff8fe037db 100644 --- a/webapp/src/redux/utils.ts +++ b/webapp/src/redux/utils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { createAction, ActionCreatorWithPayload, diff --git a/webapp/src/services/api/auth.ts b/webapp/src/services/api/auth.ts index 038f4c55ed..f5ec9407df 100644 --- a/webapp/src/services/api/auth.ts +++ b/webapp/src/services/api/auth.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import axios from "axios"; import client from "./client"; import { RefreshDTO as UserTokensDTO } from "../../common/types"; diff --git a/webapp/src/services/api/client.ts b/webapp/src/services/api/client.ts index 5ff02eb13b..1eae8d860e 100644 --- a/webapp/src/services/api/client.ts +++ b/webapp/src/services/api/client.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import axios from "axios"; import debug from "debug"; import Cookies from "js-cookie"; diff --git a/webapp/src/services/api/downloads.ts b/webapp/src/services/api/downloads.ts index 4961bd1b3d..452df236a0 100644 --- a/webapp/src/services/api/downloads.ts +++ b/webapp/src/services/api/downloads.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { getConfig } from "../config"; import client from "./client"; diff --git a/webapp/src/services/api/maintenance.ts b/webapp/src/services/api/maintenance.ts index 5cc707a1b7..f0bcd0ee99 100644 --- a/webapp/src/services/api/maintenance.ts +++ b/webapp/src/services/api/maintenance.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import client from "./client"; export const getMaintenanceMode = async (): Promise => { diff --git a/webapp/src/services/api/matrix.ts b/webapp/src/services/api/matrix.ts index 1eff05f7c9..e7d6bee7a5 100644 --- a/webapp/src/services/api/matrix.ts +++ b/webapp/src/services/api/matrix.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AxiosRequestConfig } from "axios"; import client from "./client"; import { @@ -10,6 +24,7 @@ import { } from "../../common/types"; import { FileDownloadTask } from "./downloads"; import { getConfig } from "../config"; +import { MatrixUpdateDTO } from "../../components/common/MatrixGrid/types"; export const getMatrixList = async ( name = "", @@ -91,16 +106,37 @@ export const deleteDataSet = async (id: string): Promise => { return res.data; }; +/** + * @deprecated Use `updateMatrix` instead. + * + * @param sid - The study ID. + * @param path - The path of the matrix. + * @param matrixEdit - The matrix edit data. + */ export const editMatrix = async ( sid: string, path: string, matrixEdit: MatrixEditDTO[], ): Promise => { - const res = await client.put( - `/v1/studies/${sid}/matrix?path=${encodeURIComponent(path)}`, + const sanitizedPath = path.startsWith("/") ? path.substring(1) : path; + + await client.put( + `/v1/studies/${sid}/matrix?path=${encodeURIComponent(sanitizedPath)}`, matrixEdit, ); - return res.data; +}; + +export const updateMatrix = async ( + studyId: string, + path: string, + updates: MatrixUpdateDTO[], +): Promise => { + const sanitizedPath = path.startsWith("/") ? path.substring(1) : path; + + await client.put( + `/v1/studies/${studyId}/matrix?path=${encodeURIComponent(sanitizedPath)}`, + updates, + ); }; export const getStudyMatrixIndex = async ( diff --git a/webapp/src/services/api/misc.ts b/webapp/src/services/api/misc.ts index b4bbe4dff0..95c40fefaf 100644 --- a/webapp/src/services/api/misc.ts +++ b/webapp/src/services/api/misc.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import client from "./client"; export interface APIVersion { diff --git a/webapp/src/services/api/studies/config/thematicTrimming/index.ts b/webapp/src/services/api/studies/config/thematicTrimming/index.ts index 0228eb98fc..c6a8bc8992 100644 --- a/webapp/src/services/api/studies/config/thematicTrimming/index.ts +++ b/webapp/src/services/api/studies/config/thematicTrimming/index.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import type { GetThematicTrimmingConfigParams, SetThematicTrimmingConfigParams, diff --git a/webapp/src/services/api/studies/config/thematicTrimming/types.ts b/webapp/src/services/api/studies/config/thematicTrimming/types.ts index 1137a9536f..4edbc2075f 100644 --- a/webapp/src/services/api/studies/config/thematicTrimming/types.ts +++ b/webapp/src/services/api/studies/config/thematicTrimming/types.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { StudyMetadata } from "../../../../../common/types"; export interface ThematicTrimmingConfig { diff --git a/webapp/src/services/api/studies/raw/index.ts b/webapp/src/services/api/studies/raw/index.ts index 63e46dc31a..9a86d92164 100644 --- a/webapp/src/services/api/studies/raw/index.ts +++ b/webapp/src/services/api/studies/raw/index.ts @@ -1,13 +1,53 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import client from "../../client"; -import type { DownloadMatrixParams } from "./types"; +import type { + DeleteFileParams, + DownloadMatrixParams, + ImportFileParams, +} from "./types"; export async function downloadMatrix(params: DownloadMatrixParams) { - const { studyId, ...rest } = params; + const { studyId, ...queryParams } = params; const url = `v1/studies/${studyId}/raw/download`; + const res = await client.get(url, { - params: rest, + params: queryParams, responseType: "blob", }); return res.data; } + +export async function importFile(params: ImportFileParams) { + const { studyId, file, onUploadProgress, ...queryParams } = params; + const url = `v1/studies/${studyId}/raw`; + const body = { file }; + + await client.putForm(url, body, { + params: { + ...queryParams, + create_missing: queryParams.createMissing, + }, + onUploadProgress, + }); +} + +export async function deleteFile(params: DeleteFileParams) { + const { studyId, path } = params; + const url = `v1/studies/${studyId}/raw`; + + await client.delete(url, { params: { path } }); +} diff --git a/webapp/src/services/api/studies/raw/types.ts b/webapp/src/services/api/studies/raw/types.ts index e524fbdc72..0ab6a84f8d 100644 --- a/webapp/src/services/api/studies/raw/types.ts +++ b/webapp/src/services/api/studies/raw/types.ts @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import type { AxiosRequestConfig } from "axios"; import type { StudyMetadata } from "../../../../common/types"; export interface DownloadMatrixParams { @@ -7,3 +22,16 @@ export interface DownloadMatrixParams { header?: boolean; index?: boolean; } + +export interface ImportFileParams { + studyId: StudyMetadata["id"]; + path: string; + file: File; + createMissing?: boolean; + onUploadProgress?: AxiosRequestConfig["onUploadProgress"]; +} + +export interface DeleteFileParams { + studyId: StudyMetadata["id"]; + path: string; +} diff --git a/webapp/src/services/api/studies/tableMode/constants.ts b/webapp/src/services/api/studies/tableMode/constants.ts index acef3d51f6..d2271a109d 100644 --- a/webapp/src/services/api/studies/tableMode/constants.ts +++ b/webapp/src/services/api/studies/tableMode/constants.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + const AREA = "areas"; const LINK = "links"; const THERMAL = "thermals"; diff --git a/webapp/src/services/api/studies/tableMode/index.ts b/webapp/src/services/api/studies/tableMode/index.ts index 03915b259e..c20d54dbeb 100644 --- a/webapp/src/services/api/studies/tableMode/index.ts +++ b/webapp/src/services/api/studies/tableMode/index.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import client from "../../client"; import { format } from "../../../../utils/stringUtils"; import type { diff --git a/webapp/src/services/api/studies/tableMode/types.ts b/webapp/src/services/api/studies/tableMode/types.ts index e20a167e27..cfea92f8e7 100644 --- a/webapp/src/services/api/studies/tableMode/types.ts +++ b/webapp/src/services/api/studies/tableMode/types.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { DeepPartial } from "react-hook-form"; import type { StudyMetadata } from "../../../../common/types"; import { TABLE_MODE_COLUMNS_BY_TYPE, TABLE_MODE_TYPES } from "./constants"; diff --git a/webapp/src/services/api/study.ts b/webapp/src/services/api/study.ts index a060bd8a16..8750b177f4 100644 --- a/webapp/src/services/api/study.ts +++ b/webapp/src/services/api/study.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AxiosRequestConfig } from "axios"; import { isBoolean, trimCharsStart } from "ramda-adjunct"; import client from "./client"; @@ -243,37 +257,6 @@ export const importStudy = async ( return res.data; }; -export const importFile = async ( - file: File, - study: string, - path: string, - onProgress?: (progress: number) => void, -): Promise => { - const options: AxiosRequestConfig = {}; - if (onProgress) { - options.onUploadProgress = (progressEvent): void => { - const percentCompleted = Math.round( - (progressEvent.loaded * 100) / (progressEvent.total || 1), - ); - onProgress(percentCompleted); - }; - } - const formData = new FormData(); - formData.append("file", file); - const restconfig = { - ...options, - headers: { - "content-type": "multipart/form-data", - }, - }; - const res = await client.put( - `/v1/studies/${study}/raw?path=${encodeURIComponent(path)}`, - formData, - restconfig, - ); - return res.data; -}; - export const launchStudy = async ( sid: string, options: LaunchOptions = {}, diff --git a/webapp/src/services/api/studydata.ts b/webapp/src/services/api/studydata.ts index a39b55f20b..a230be85bf 100644 --- a/webapp/src/services/api/studydata.ts +++ b/webapp/src/services/api/studydata.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { LinkCreationInfoDTO, LinkInfoWithUI, diff --git a/webapp/src/services/api/tasks.ts b/webapp/src/services/api/tasks.ts index 27b0bec58f..3629646b00 100644 --- a/webapp/src/services/api/tasks.ts +++ b/webapp/src/services/api/tasks.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { TaskDTO, TaskStatus } from "../../common/types"; import client from "./client"; diff --git a/webapp/src/services/api/user.ts b/webapp/src/services/api/user.ts index e8382bc180..0217bd26ed 100644 --- a/webapp/src/services/api/user.ts +++ b/webapp/src/services/api/user.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as RA from "ramda-adjunct"; import client from "./client"; import { diff --git a/webapp/src/services/api/variant.ts b/webapp/src/services/api/variant.ts index 3e8f76132e..0825ef7d1b 100644 --- a/webapp/src/services/api/variant.ts +++ b/webapp/src/services/api/variant.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import client from "./client"; import { CommandDTO, diff --git a/webapp/src/services/api/xpansion.ts b/webapp/src/services/api/xpansion.ts index fb66a08a9a..841d280d17 100644 --- a/webapp/src/services/api/xpansion.ts +++ b/webapp/src/services/api/xpansion.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { AxiosRequestConfig } from "axios"; import { MatrixType } from "../../common/types"; import { diff --git a/webapp/src/services/config.ts b/webapp/src/services/config.ts index 4f93290c8b..2eed7bff46 100644 --- a/webapp/src/services/config.ts +++ b/webapp/src/services/config.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import debug from "debug"; import axios from "axios"; import moment from "moment"; diff --git a/webapp/src/services/utils/index.ts b/webapp/src/services/utils/index.ts index f7980ee2bd..27cb441d65 100644 --- a/webapp/src/services/utils/index.ts +++ b/webapp/src/services/utils/index.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import moment from "moment"; import debug from "debug"; import i18n, { TFunction } from "i18next"; diff --git a/webapp/src/services/utils/localStorage.ts b/webapp/src/services/utils/localStorage.ts index f55586feba..11bd432e0d 100644 --- a/webapp/src/services/utils/localStorage.ts +++ b/webapp/src/services/utils/localStorage.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as RA from "ramda-adjunct"; import packages from "../../../package.json"; import { UserInfo } from "../../common/types"; diff --git a/webapp/src/services/webSockets.ts b/webapp/src/services/webSockets.ts index e61bf0f4b7..18a250f019 100644 --- a/webapp/src/services/webSockets.ts +++ b/webapp/src/services/webSockets.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import debug from "debug"; import * as RA from "ramda-adjunct"; import { diff --git a/webapp/src/tests/mocks/mockGetBoundingClientRect.ts b/webapp/src/tests/mocks/mockGetBoundingClientRect.ts new file mode 100644 index 0000000000..a66544a9d0 --- /dev/null +++ b/webapp/src/tests/mocks/mockGetBoundingClientRect.ts @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +/** + * Mocks the `getBoundingClientRect` method of the Element prototype. + * + * This utility function overrides the default `getBoundingClientRect` method + * to return predetermined values. This is particularly useful in test environments + * where the dimensions and positioning of elements cannot be accurately measured + * as they would be in a fully rendered browser environment. By mocking these values, + * tests can assert layout and dimension-related properties in a controlled and + * predictable manner. + * + * Usage: + * This mock should be set up in the setup phase of your tests, typically in a + * `beforeEach` block, to ensure that every test runs with the same initial conditions. + * Remember to restore or reset the original function after your tests to avoid + * side effects, especially if other tests depend on the original behavior. + * + * @example + * describe('Your Test Suite', () => { + * beforeEach(() => { + * mockGetBoundingClientRect(); + * }); + * + * afterEach(() => { + * vi.restoreAllMocks(); + * }); + * + * test('your test', () => { + * // your test code here + * }); + * }); + * + * The mock is implemented by replacing `Element.prototype.getBoundingClientRect` + * with a custom function that returns fixed dimensions: + * - `width`: Calculated from the computed style of the element. + * - `height`: Calculated from the computed style of the element. + * - `top`: Always 0, simulating the element's position relative to the viewport. + * - `left`: Always 0, simulating the element's position relative to the viewport. + * - `bottom`: Calculated as the height, simulating the element's lower boundary relative to the viewport. + * - `right`: Calculated as the width, simulating the element's right boundary relative to the viewport. + * - `x`: Always 0, representing the x-coordinate of the element's bounding box. + * - `y`: Always 0, representing the y-coordinate of the element's bounding box. + * - `toJSON`: A function that returns an object representation of the bounding box. + * + * Note that the computed dimensions are based on the element's computed style at the time + * of the function call, so tests should ensure that relevant styles are appropriately set + * or mocked to reflect expected values. + * @see https://developer.mozilla.org/fr/docs/Web/API/Element/getBoundingClientRect + */ +export const mockGetBoundingClientRect = () => { + Element.prototype.getBoundingClientRect = vi.fn(function (this: Element) { + const { width, height } = window.getComputedStyle(this); + const rectWidth = parseInt(width, 10); + const rectHeight = parseInt(height, 10); + + return { + width: rectWidth, + height: rectHeight, + top: 0, + left: 0, + bottom: rectHeight, + right: rectWidth, + x: 0, + y: 0, + toJSON: () => ({ + width: rectWidth, + height: rectHeight, + top: 0, + left: 0, + bottom: rectHeight, + right: rectWidth, + x: 0, + y: 0, + }), + }; + }); +}; diff --git a/webapp/src/tests/mocks/mockHTMLCanvasElement.ts b/webapp/src/tests/mocks/mockHTMLCanvasElement.ts new file mode 100644 index 0000000000..84e22dd58e --- /dev/null +++ b/webapp/src/tests/mocks/mockHTMLCanvasElement.ts @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +/** + * Creates a mock for the HTML Canvas API in a testing environment. + * + * This function addresses the problem of testing components that rely on the + * Canvas API in a Node.js environment, where the DOM and Canvas are not natively + * available. Specifically, it solves issues related to testing components that + * use libraries like @glideapps/glide-data-grid, which depend on canvas functionality. + * + * The mock provides stub implementations for commonly used CanvasRenderingContext2D + * methods, allowing tests to run without throwing "not implemented" errors that + * would typically occur when canvas methods are called in a non-browser environment. + * + * @returns An object containing the mocked context and getContext function. + */ +export const mockHTMLCanvasElement = () => { + /** + * A partial mock of CanvasRenderingContext2D. + * Only the most commonly used methods are mocked to keep the implementation lean. + * Additional methods can be added here as needed. + */ + const contextMock: Partial = { + measureText: vi.fn().mockReturnValue({ + width: 0, + actualBoundingBoxAscent: 0, + actualBoundingBoxDescent: 0, + actualBoundingBoxLeft: 0, + actualBoundingBoxRight: 0, + fontBoundingBoxAscent: 0, + fontBoundingBoxDescent: 0, + }), + fillRect: vi.fn(), + clearRect: vi.fn(), + getImageData: vi + .fn() + .mockReturnValue({ data: new Uint8ClampedArray(), width: 0, height: 0 }), + save: vi.fn(), + fillText: vi.fn(), + restore: vi.fn(), + beginPath: vi.fn(), + moveTo: vi.fn(), + lineTo: vi.fn(), + closePath: vi.fn(), + translate: vi.fn(), + scale: vi.fn(), + rotate: vi.fn(), + arc: vi.fn(), + rect: vi.fn(), + }; + + const getContextMock = vi.fn().mockReturnValue(contextMock); + + // Override the getContext method on the HTMLCanvasElement prototype + window.HTMLCanvasElement.prototype.getContext = getContextMock; + + return { contextMock, getContextMock }; +}; diff --git a/webapp/src/tests/mocks/mockResizeObserver.ts b/webapp/src/tests/mocks/mockResizeObserver.ts new file mode 100644 index 0000000000..588233a277 --- /dev/null +++ b/webapp/src/tests/mocks/mockResizeObserver.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +/** + * This is a mock implementation of the global `ResizeObserver`. + * ResizeObserver is a web API used to monitor changes in an element's size. + * As Vitest runs in a Node environment where certain browser-specific APIs like ResizeObserver are not available, + * we need to mock these APIs to prevent errors during testing and ensure that components relying on them can be tested. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver + */ +global.ResizeObserver = vi.fn().mockImplementation(() => ({ + // The `observe` method is responsible for starting the observation of size changes on the specified element. + // We mock this method to simply track calls (since actual DOM measurements aren't possible in Jest or Vitest environments). + observe: vi.fn(), + + // The `unobserve` method stops the observation of an element. It's essential for cleanup in real usage to avoid memory leaks, + // but here it's just a mock to ensure we can verify calls to it during tests. + unobserve: vi.fn(), + + // The `disconnect` method stops all observations by this instance of ResizeObserver. + // This is used to clean up observers when a component unmounts. The mock helps to simulate and test these cleanup behaviors. + disconnect: vi.fn(), +})); diff --git a/webapp/src/tests/setup.ts b/webapp/src/tests/setup.ts index d1e9ef6bae..5512f0a058 100644 --- a/webapp/src/tests/setup.ts +++ b/webapp/src/tests/setup.ts @@ -1,7 +1,22 @@ -import * as matchers from "@testing-library/jest-dom/matchers"; -import "@testing-library/jest-dom"; +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import "@testing-library/jest-dom/vitest"; +import { expect, afterEach } from "vitest"; import { cleanup } from "@testing-library/react"; -import { expect } from "vitest"; +import * as matchers from "@testing-library/jest-dom/matchers"; +import "./mocks/mockResizeObserver"; // Extend Vitest's expect function with jest-dom matchers for enhanced DOM assertions. expect.extend(matchers); diff --git a/webapp/src/theme.ts b/webapp/src/theme.ts index efbe96392a..6776e32e6e 100644 --- a/webapp/src/theme.ts +++ b/webapp/src/theme.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import * as React from "react"; import { createTheme } from "@mui/material/styles"; @@ -75,6 +89,13 @@ const theme = createTheme({ }, }, }, + MuiListSubheader: { + styleOverrides: { + root: { + backgroundColor: "#222333", + }, + }, + }, MuiAlert: { styleOverrides: { root: { diff --git a/webapp/src/types/i18next.d.ts b/webapp/src/types/i18next.d.ts index 557b3de4e2..a9f77c3835 100644 --- a/webapp/src/types/i18next.d.ts +++ b/webapp/src/types/i18next.d.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import "i18next"; declare module "i18next" { diff --git a/webapp/src/types/jsoneditor.d.ts b/webapp/src/types/jsoneditor.d.ts new file mode 100644 index 0000000000..b1dd2a44c6 --- /dev/null +++ b/webapp/src/types/jsoneditor.d.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +import "jsoneditor"; + +declare module "jsoneditor" { + export interface HistoryItem { + action: string; + params: object; + timestamp: Date; + } + + export default interface JSONEditor { + /** + * Only available for mode `code`. + */ + aceEditor?: AceAjax.Editor; + /** + * Expand all fields. Only applicable for mode `tree`, `view`, and `form`. + */ + expandAll?: VoidFunction; + /** + * Only available for mode `tree`, `form`, and `preview`. + */ + history?: { + /** + * Only available for mode `tree`, and `form`. + */ + history?: HistoryItem[]; + index: number; + onChange: () => void; + }; + menu: HTMLDivElement; + } +} diff --git a/webapp/src/types/reset.d.ts b/webapp/src/types/reset.d.ts index 875dabbf65..ceb285f769 100644 --- a/webapp/src/types/reset.d.ts +++ b/webapp/src/types/reset.d.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import "@total-typescript/ts-reset/array-includes"; import "@total-typescript/ts-reset/array-index-of"; import "@total-typescript/ts-reset/filter-boolean"; diff --git a/webapp/src/types/vite-env.d.ts b/webapp/src/types/vite-env.d.ts new file mode 100644 index 0000000000..933430dd54 --- /dev/null +++ b/webapp/src/types/vite-env.d.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +declare const __BUILD_TIMESTAMP__: string; diff --git a/webapp/src/utils/feUtils.ts b/webapp/src/utils/feUtils.ts index 636fcb82ea..8d6c75de6f 100644 --- a/webapp/src/utils/feUtils.ts +++ b/webapp/src/utils/feUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { HTMLInputTypeAttribute } from "react"; export interface InputObject { diff --git a/webapp/src/utils/fileUtils.ts b/webapp/src/utils/fileUtils.ts index 0233d6f984..f7d3895817 100644 --- a/webapp/src/utils/fileUtils.ts +++ b/webapp/src/utils/fileUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /** * Triggers the download of a file with the given data and name. * diff --git a/webapp/src/utils/fnUtils.ts b/webapp/src/utils/fnUtils.ts index dd32ac4c97..426dc01179 100644 --- a/webapp/src/utils/fnUtils.ts +++ b/webapp/src/utils/fnUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + /** * A utility function designed to be used as a placeholder or stub. It can be used in situations where you might * otherwise be tempted to disable an ESLint rule temporarily, such as when you need to pass a function that diff --git a/webapp/src/utils/i18nUtils.ts b/webapp/src/utils/i18nUtils.ts index c613deab68..185f3dbe26 100644 --- a/webapp/src/utils/i18nUtils.ts +++ b/webapp/src/utils/i18nUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import i18n from "../i18n"; /** diff --git a/webapp/src/utils/muiUtils.ts b/webapp/src/utils/muiUtils.ts index e99d875109..6ab5f19169 100644 --- a/webapp/src/utils/muiUtils.ts +++ b/webapp/src/utils/muiUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { SxProps, Theme } from "@mui/material"; export function mergeSxProp( diff --git a/webapp/src/utils/pathUtils.ts b/webapp/src/utils/pathUtils.ts new file mode 100644 index 0000000000..dc30542228 --- /dev/null +++ b/webapp/src/utils/pathUtils.ts @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + +/** + * Get parent paths of a given path. + * + * @example + * getParentPaths("a/b/c/d"); // Returns: ["a", "a/b", "a/b/c"] + * + * @param path - The path from which to get the parent paths. + * @returns The parent paths. + */ +export function getParentPaths(path: string) { + return path + .split("/") + .slice(0, -1) // Remove the last item + .map((_, index, arr) => arr.slice(0, index + 1).join("/")); +} diff --git a/webapp/src/utils/reactUtils.ts b/webapp/src/utils/reactUtils.ts index 0821bd4b82..a7b71b5468 100644 --- a/webapp/src/utils/reactUtils.ts +++ b/webapp/src/utils/reactUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { setRef } from "@mui/material"; export function isDependencyList( diff --git a/webapp/src/utils/stringUtils.ts b/webapp/src/utils/stringUtils.ts index 823829fb29..6c829d37aa 100644 --- a/webapp/src/utils/stringUtils.ts +++ b/webapp/src/utils/stringUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { deburr } from "lodash"; import * as R from "ramda"; import * as RA from "ramda-adjunct"; diff --git a/webapp/src/utils/studiesUtils.ts b/webapp/src/utils/studiesUtils.ts index 4072e09c51..774e80ed13 100644 --- a/webapp/src/utils/studiesUtils.ts +++ b/webapp/src/utils/studiesUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import moment from "moment"; import * as R from "ramda"; import * as RA from "ramda-adjunct"; diff --git a/webapp/src/utils/tsUtils.ts b/webapp/src/utils/tsUtils.ts index f368e9b8a4..730c211486 100644 --- a/webapp/src/utils/tsUtils.ts +++ b/webapp/src/utils/tsUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { O } from "ts-toolbelt"; /** diff --git a/webapp/src/utils/validationUtils.ts b/webapp/src/utils/validationUtils.ts index e6d85c21ba..3d4c168697 100644 --- a/webapp/src/utils/validationUtils.ts +++ b/webapp/src/utils/validationUtils.ts @@ -1,3 +1,17 @@ +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { t } from "i18next"; //////////////////////////////////////////////////////////////// diff --git a/webapp/src/vite-env.d.ts b/webapp/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a0..0000000000 --- a/webapp/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/webapp/tsconfig.json b/webapp/tsconfig.json index 3a20f675ad..c9e8d32271 100644 --- a/webapp/tsconfig.json +++ b/webapp/tsconfig.json @@ -2,7 +2,11 @@ "compilerOptions": { "target": "es2022", "useDefineForClassFields": true, - "lib": ["ES2022", "DOM", "DOM.Iterable"], + "lib": [ + "ES2022", + "DOM", + "DOM.Iterable", + ], "module": "ESNext", "skipLibCheck": true, @@ -13,7 +17,11 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", - "types": ["vitest/globals", "vitest/jsdom"], + "types": [ + "vite/client", + "vitest/globals", + "vitest/jsdom", + ], /* Linting */ "strict": true, diff --git a/webapp/tsconfig.node.json b/webapp/tsconfig.node.json index b1b8569880..15b8ba2c14 100644 --- a/webapp/tsconfig.node.json +++ b/webapp/tsconfig.node.json @@ -5,7 +5,10 @@ "module": "ESNext", "moduleResolution": "bundler", "allowSyntheticDefaultImports": true, - "types": ["vitest/globals", "vitest/jsdom"] + "types": [ + "vitest/globals", + "vitest/jsdom", + ] }, "include": ["vite.config.ts"] } diff --git a/webapp/vite.config.ts b/webapp/vite.config.ts index 7cce8d327b..9b7a5b5cef 100644 --- a/webapp/vite.config.ts +++ b/webapp/vite.config.ts @@ -1,4 +1,17 @@ -/// +/** + * Copyright (c) 2024, RTE (https://www.rte-france.com) + * + * See AUTHORS.txt + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of the Antares project. + */ + import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; @@ -11,6 +24,11 @@ export default defineConfig(({ mode }) => { return { // Serve the web app at the `/static` entry point on Desktop mode (cf. 'antarest/main.py') base: isDesktopMode ? "/static/" : "/", + // Entries will be defined as globals during dev and statically replaced during build + define: { + // Not working in dev without `JSON.stringify` + __BUILD_TIMESTAMP__: JSON.stringify(Date.now()), + }, esbuild: { // Remove logs safely when building production bundle // https://esbuild.github.io/api/#pure @@ -30,7 +48,7 @@ export default defineConfig(({ mode }) => { }, }, test: { - globals: true, // Use the APIs globally + globals: true, // Use the APIs globally, environment: "jsdom", css: true, setupFiles: "./src/tests/setup.ts",