From cd4a6f02c99161a895a343789d3d407fe53cf760 Mon Sep 17 00:00:00 2001 From: Sigurd Borge Date: Mon, 14 Oct 2024 13:17:45 +0200 Subject: [PATCH] Feat/update project management (#7) * Added default properties to binding constraints * Added bindingconstraints.ini file * Added default value 0 for constraint weight * Added the weight and offset combination in the ini file, as well as disabled interpolation in the ini tool * Refactored binding constraints to be tracked in the service instead of the study to allow correct handling of ini file * Make types-requests match requests version to as they're meant to be aligned, also updated for the new DATA definition in types-requests * Added authors and linting rules to pyproject.toml. The rules chosen are the ruff defaults + sorting imports * Cleaned up imports to match the new linting rule * Moved pytest and mypy options into pyproject.toml * Added isort options to pyproject.toml and updated imports again * Added __init__.py to integration to correct import behavior * Added a first tox.ini as tox for now doesn't have proper pyproject.toml support, also updated README.md with a bit of information about how to use tox * Moved coverage configuration into pyproject.toml and sorted requirements.txt and requirements-dev.txt plus made sure coverage can read toml * Fixed missing header and added header fixes to tox.ini * Updated .gitignore to remove some build caching and organize a bit better * Added more information to pyproject.toml and organized it better. Some cleanup after rebase. * Bumped tox version to allow tox configuration in pyproject.toml and deleted tox.ini. * First tiny step of documentation added using mkdocs and the template from Antares Simulator. Included possibility to parse documentation from docstrings. * Reverting to individual configuration files as per discussion --- .gitignore | 33 ++++++++++--- README.md | 44 +++++++++++++++-- docs/assets/Icone.png | Bin 0 -> 35546 bytes docs/assets/antares.png | Bin 0 -> 26612 bytes docs/assets/logo.png | Bin 0 -> 10674 bytes docs/index.md | 46 ++++++++++++++++++ docs/quickstart.md | 10 ++++ mkdocs.yml | 34 +++++++++++++ pyproject.toml | 30 ++++++++++-- requirements-dev.txt | 12 +++-- requirements.txt | 8 +-- ruff.toml | 20 ++++++++ src/antares/api_conf/request_wrapper.py | 12 ++++- src/antares/model/area.py | 7 +-- src/antares/model/binding_constraint.py | 3 +- src/antares/model/hydro.py | 3 +- src/antares/model/link.py | 2 +- src/antares/model/settings/__init__.py | 2 +- src/antares/model/st_storage.py | 1 + src/antares/model/study.py | 19 ++++---- src/antares/service/api_services/area_api.py | 28 +++++------ .../api_services/binding_constraint_api.py | 8 +-- src/antares/service/api_services/link_api.py | 2 +- .../service/api_services/renewable_api.py | 2 +- .../service/api_services/st_storage_api.py | 6 +-- src/antares/service/api_services/study_api.py | 10 ++-- .../service/api_services/thermal_api.py | 4 +- src/antares/service/base_services.py | 18 +++---- .../service/local_services/area_local.py | 17 ++++--- .../binding_constraint_local.py | 12 ++--- .../service/local_services/link_local.py | 7 +-- .../service/local_services/study_local.py | 2 +- src/antares/service/service_factory.py | 6 +-- src/antares/tools/all_optional_meta.py | 1 + src/antares/tools/contents_tool.py | 1 + src/antares/tools/ini_tool.py | 2 +- src/antares/tools/prepro_folder.py | 4 +- tests/antares/delete/test_delete_api.py | 6 +-- .../services/api_services/test_area_api.py | 27 +++++----- .../test_binding_constraint_api.py | 10 ++-- .../services/api_services/test_link_api.py | 4 +- .../api_services/test_renewable_api.py | 10 ++-- .../api_services/test_st_storage_api.py | 8 +-- .../services/api_services/test_study_api.py | 20 ++++---- .../services/api_services/test_thermal_api.py | 10 ++-- .../services/local_services/conftest.py | 10 ++-- .../services/local_services/test_area.py | 16 +++--- .../services/local_services/test_study.py | 16 +++--- tests/antares/tools/conftest.py | 3 +- tests/antares/tools/test_time_series_tool.py | 3 +- tests/integration/__init__.py | 12 +++++ tests/integration/antares_web_desktop.py | 1 + tests/integration/test_web_client.py | 29 +++++------ tox.ini | 24 +++++++++ 54 files changed, 440 insertions(+), 185 deletions(-) create mode 100644 docs/assets/Icone.png create mode 100644 docs/assets/antares.png create mode 100644 docs/assets/logo.png create mode 100644 docs/index.md create mode 100644 docs/quickstart.md create mode 100644 mkdocs.yml create mode 100644 ruff.toml create mode 100644 tests/integration/__init__.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index cf40b51c..47964111 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,31 @@ -.vscode +# Some categories and items copied from https://github.com/github/gitignore/blob/main/Python.gitignore + +# Byte-compiled / optimized / DLL files __pycache__ -**.ipynb -.idea -venv -.env +# Distribution / packaging +.Python +build/ +dist/ +sdist/ +*.egg-info/ +site/ + +# Unit test / coverage reports .coverage coverage.xml -AntaresWebDesktop +.tox/ + +# Environments +.env +.venv +env/ +venv/ + +# Jupyter notebooks +**.ipynb + +# Other +.vscode +.idea +AntaresWebDesktop/ diff --git a/README.md b/README.md index bf4656b6..d3b49718 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,46 @@ -Antares Craft python library is currently under construction. When completed it will allow to create, update and read antares studies. +# antares_craft +[![github ci](https://github.com/AntaresSimulatorTeam/antares_craft/actions/workflows/ci.yml/badge.svg)](https://github.com/AntaresSimulatorTeam/antares_craft/actions/workflows/ci.yml) + +## about + +Antares Craft python library is currently under construction. When completed it will allow to create, update and read +antares studies. This project only supports antares studies with a version v8.8 or higher. -To reformat your code, use this command line : `ruff check src/ tests/ --fix && ruff format src/ tests/` +## developers +### install dev requirements + +Install dev requirements with `pip install -r requirements-dev.txt` + +### linting and formatting + +To reformat your code, use this command line: `ruff check src/ tests/ --fix && ruff format src/ tests/` -To launch integration tests you'll need an AntaresWebDesktop instance on your local env (at least the v.2.17.3, **currently running in 2.17.5**). -To install it, download it from the last [Antares Web release](https://github.com/AntaresSimulatorTeam/AntaREST/releases) (inside the assets list). +### typechecking + +To typecheck your code, use this command line: `mypy` + +### integration testing + +To launch integration tests you'll need an AntaresWebDesktop instance on your local env (at least the v.2.17.3, +**currently running in 2.17.5**). +To install it, download it from the last [Antares Web release](https://github.com/AntaresSimulatorTeam/AntaREST/releases) +(inside the assets list). Then, unzip it at the root of this repository and rename the folder `AntaresWebDesktop`. *NB*: The expected folder structure is the following: `antares_craft/AntaresWebDesktop/config.yaml` + +### tox +To use [tox](https://tox.wiki/) to run unit tests in multiple python versions at the same time as linting and formatting +with ruff and typing with mypy: +1) As the dev requirements include [uv](https://docs.astral.sh/uv/) and `tox-uv` there is no need to install python +versions, `uv` will do this for you. +2) Use `tox -p` to run the environments in parallel to save time, this will create virtual environment with the +necessary python versions the first time you run tox. + +### mkdocs +Smallest beginning of `mkdocs` included more as proof of concept than anything, theme and logo copied from [Antares +Simulator](https://github.com/AntaresSimulatorTeam/Antares_Simulator). +1) To preview the docs on your local machine run `mkdocs serve`. +2) To build the static site for publishing for example on [Read the Docs](https://readthedocs.io) use `mkdocs build`. +3) To flesh out the documentation see [mkdoc guides](https://www.mkdocs.org/user-guide/). diff --git a/docs/assets/Icone.png b/docs/assets/Icone.png new file mode 100644 index 0000000000000000000000000000000000000000..597698eae9c51effbb5169d8536a2b7a9aeff492 GIT binary patch literal 35546 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 literal 0 HcmV?d00001 diff --git a/docs/assets/antares.png b/docs/assets/antares.png new file mode 100644 index 0000000000000000000000000000000000000000..0115f08967600b0cbb3e56e25196f134ebea6974 GIT binary patch literal 26612 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 literal 0 HcmV?d00001 diff --git a/docs/assets/logo.png b/docs/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd094175dd4a9bb6669d76bead0ea9584622820 GIT binary patch literal 10674 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 requests.Response: diff --git a/src/antares/model/area.py b/src/antares/model/area.py index 6ab1e4db..8b016916 100644 --- a/src/antares/model/area.py +++ b/src/antares/model/area.py @@ -17,14 +17,15 @@ """ from types import MappingProxyType -from typing import Optional, Dict, List, Any, Mapping, Set +from typing import Any, Dict, List, Mapping, Optional, Set import pandas as pd + from pydantic import BaseModel, computed_field from pydantic.alias_generators import to_camel from antares.model.commons import FilterOption, sort_filter_values -from antares.model.hydro import HydroProperties, HydroMatrixName, Hydro +from antares.model.hydro import Hydro, HydroMatrixName, HydroProperties from antares.model.load import Load from antares.model.misc_gen import MiscGen from antares.model.renewable import RenewableCluster, RenewableClusterProperties @@ -34,7 +35,7 @@ from antares.model.thermal import ThermalCluster, ThermalClusterProperties from antares.model.wind import Wind from antares.tools.all_optional_meta import all_optional_model -from antares.tools.contents_tool import transform_name_to_id, EnumIgnoreCase +from antares.tools.contents_tool import EnumIgnoreCase, transform_name_to_id class AdequacyPatchMode(EnumIgnoreCase): diff --git a/src/antares/model/binding_constraint.py b/src/antares/model/binding_constraint.py index 47f30bd0..e5572f22 100644 --- a/src/antares/model/binding_constraint.py +++ b/src/antares/model/binding_constraint.py @@ -11,9 +11,10 @@ # This file is part of the Antares project. from enum import Enum -from typing import Optional, Union, List, Any, Dict +from typing import Any, Dict, List, Optional, Union import pandas as pd + from pydantic import BaseModel, Field, model_validator from pydantic.alias_generators import to_camel diff --git a/src/antares/model/hydro.py b/src/antares/model/hydro.py index 811c2e8f..345d7c65 100644 --- a/src/antares/model/hydro.py +++ b/src/antares/model/hydro.py @@ -11,9 +11,10 @@ # This file is part of the Antares project. from enum import Enum -from typing import Optional, Dict +from typing import Dict, Optional import pandas as pd + from pydantic import BaseModel from pydantic.alias_generators import to_camel diff --git a/src/antares/model/link.py b/src/antares/model/link.py index 95f0f983..a77933c3 100644 --- a/src/antares/model/link.py +++ b/src/antares/model/link.py @@ -11,7 +11,7 @@ # This file is part of the Antares project. from enum import Enum -from typing import Optional, Set, Mapping +from typing import Mapping, Optional, Set from pydantic import BaseModel diff --git a/src/antares/model/settings/__init__.py b/src/antares/model/settings/__init__.py index 28c477f0..be48843f 100644 --- a/src/antares/model/settings/__init__.py +++ b/src/antares/model/settings/__init__.py @@ -10,7 +10,7 @@ # # This file is part of the Antares project. -from typing import Optional, Dict +from typing import Dict, Optional from pydantic import BaseModel diff --git a/src/antares/model/st_storage.py b/src/antares/model/st_storage.py index 25f6c2f9..ebaf5619 100644 --- a/src/antares/model/st_storage.py +++ b/src/antares/model/st_storage.py @@ -14,6 +14,7 @@ from typing import Optional import pandas as pd + from pydantic import BaseModel from pydantic.alias_generators import to_camel diff --git a/src/antares/model/study.py b/src/antares/model/study.py index e6a7a2b2..95c37e78 100644 --- a/src/antares/model/study.py +++ b/src/antares/model/study.py @@ -13,9 +13,10 @@ import logging import os import time + from pathlib import Path from types import MappingProxyType -from typing import Optional, Dict, List, Any +from typing import Any, Dict, List, Optional import pandas as pd @@ -25,7 +26,7 @@ from antares.exceptions.exceptions import APIError, StudyCreationError from antares.model.area import Area, AreaProperties, AreaUi from antares.model.binding_constraint import BindingConstraint, BindingConstraintProperties, ConstraintTerm -from antares.model.link import Link, LinkUi, LinkProperties +from antares.model.link import Link, LinkProperties, LinkUi from antares.model.settings import StudySettings from antares.service.api_services.study_api import _returns_study_settings from antares.service.base_services import BaseStudyService @@ -46,15 +47,14 @@ def create_study_api( ) -> "Study": """ Args: - - study_name: antares study name to be created - version: antares version - api_config: host and token config for API - settings: study settings. If not provided, AntaresWeb will use its default values. + study_name: antares study name to be created + version: antares version + api_config: host and token config for API + settings: study settings. If not provided, AntaresWeb will use its default values. Raises: - MissingTokenError if api_token is missing - StudyCreationError if an HTTP Exception occurs + MissingTokenError if api_token is missing + StudyCreationError if an HTTP Exception occurs """ session = api_config.set_up_api_conf() @@ -83,6 +83,7 @@ def create_study_local( ) -> "Study": """ Create a directory structure for the study with empty files. + Args: study_name: antares study name to be created version: antares version for study diff --git a/src/antares/service/api_services/area_api.py b/src/antares/service/api_services/area_api.py index 19debb12..6d0fb382 100644 --- a/src/antares/service/api_services/area_api.py +++ b/src/antares/service/api_services/area_api.py @@ -11,7 +11,7 @@ # This file is part of the Antares project. from pathlib import PurePosixPath -from typing import Optional, Dict, Union, List +from typing import Dict, List, Optional, Union import pandas as pd @@ -20,35 +20,35 @@ from antares.exceptions.exceptions import ( APIError, AreaCreationError, - AreaPropertiesUpdateError, AreaDeletionError, + AreaPropertiesUpdateError, AreaUiUpdateError, - MatrixUploadError, HydroCreationError, - ThermalCreationError, + LoadMatrixDownloadError, + LoadMatrixUploadError, + MatrixUploadError, RenewableCreationError, - STStorageCreationError, - ThermalDeletionError, RenewableDeletionError, + STStorageCreationError, STStorageDeletionError, - LoadMatrixUploadError, - LoadMatrixDownloadError, + ThermalCreationError, + ThermalDeletionError, ) -from antares.model.area import AreaProperties, AreaUi, Area -from antares.model.hydro import HydroProperties, HydroMatrixName, Hydro +from antares.model.area import Area, AreaProperties, AreaUi +from antares.model.hydro import Hydro, HydroMatrixName, HydroProperties from antares.model.load import Load from antares.model.misc_gen import MiscGen -from antares.model.renewable import RenewableClusterProperties, RenewableCluster +from antares.model.renewable import RenewableCluster, RenewableClusterProperties from antares.model.reserves import Reserves from antares.model.solar import Solar -from antares.model.st_storage import STStorageProperties, STStorage -from antares.model.thermal import ThermalClusterProperties, ThermalCluster +from antares.model.st_storage import STStorage, STStorageProperties +from antares.model.thermal import ThermalCluster, ThermalClusterProperties from antares.model.wind import Wind from antares.service.base_services import ( BaseAreaService, + BaseRenewableService, BaseShortTermStorageService, BaseThermalService, - BaseRenewableService, ) from antares.tools.contents_tool import AreaUiResponse from antares.tools.matrix_tool import prepare_args_replace_matrix diff --git a/src/antares/service/api_services/binding_constraint_api.py b/src/antares/service/api_services/binding_constraint_api.py index a2abac9b..167ef364 100644 --- a/src/antares/service/api_services/binding_constraint_api.py +++ b/src/antares/service/api_services/binding_constraint_api.py @@ -11,7 +11,7 @@ # This file is part of the Antares project. from pathlib import PurePosixPath -from typing import Optional, List +from typing import List, Optional import pandas as pd @@ -20,17 +20,17 @@ from antares.exceptions.exceptions import ( APIError, BindingConstraintCreationError, - ConstraintTermDeletionError, - ConstraintPropertiesUpdateError, ConstraintMatrixDownloadError, ConstraintMatrixUpdateError, + ConstraintPropertiesUpdateError, ConstraintTermAdditionError, + ConstraintTermDeletionError, ) from antares.model.binding_constraint import ( BindingConstraint, BindingConstraintProperties, - ConstraintTerm, ConstraintMatrixName, + ConstraintTerm, ) from antares.service.api_services.utils import get_matrix from antares.service.base_services import BaseBindingConstraintService diff --git a/src/antares/service/api_services/link_api.py b/src/antares/service/api_services/link_api.py index 5f28787f..2e5346ff 100644 --- a/src/antares/service/api_services/link_api.py +++ b/src/antares/service/api_services/link_api.py @@ -23,7 +23,7 @@ LinkUiUpdateError, ) from antares.model.area import Area -from antares.model.link import LinkProperties, LinkUi, Link +from antares.model.link import Link, LinkProperties, LinkUi from antares.service.base_services import BaseLinkService diff --git a/src/antares/service/api_services/renewable_api.py b/src/antares/service/api_services/renewable_api.py index 03875c2e..199aba5c 100644 --- a/src/antares/service/api_services/renewable_api.py +++ b/src/antares/service/api_services/renewable_api.py @@ -16,7 +16,7 @@ from antares.api_conf.api_conf import APIconf from antares.api_conf.request_wrapper import RequestWrapper -from antares.exceptions.exceptions import APIError, RenewablePropertiesUpdateError, RenewableMatrixDownloadError +from antares.exceptions.exceptions import APIError, RenewableMatrixDownloadError, RenewablePropertiesUpdateError from antares.model.renewable import RenewableCluster, RenewableClusterProperties from antares.service.api_services.utils import get_matrix from antares.service.base_services import BaseRenewableService diff --git a/src/antares/service/api_services/st_storage_api.py b/src/antares/service/api_services/st_storage_api.py index 3860c531..0879daf6 100644 --- a/src/antares/service/api_services/st_storage_api.py +++ b/src/antares/service/api_services/st_storage_api.py @@ -16,11 +16,11 @@ from antares.api_conf.request_wrapper import RequestWrapper from antares.exceptions.exceptions import ( APIError, - STStoragePropertiesUpdateError, - STStorageMatrixUploadError, STStorageMatrixDownloadError, + STStorageMatrixUploadError, + STStoragePropertiesUpdateError, ) -from antares.model.st_storage import STStorage, STStorageProperties, STStorageMatrixName +from antares.model.st_storage import STStorage, STStorageMatrixName, STStorageProperties from antares.service.base_services import BaseShortTermStorageService diff --git a/src/antares/service/api_services/study_api.py b/src/antares/service/api_services/study_api.py index 027e92c8..8f3ec019 100644 --- a/src/antares/service/api_services/study_api.py +++ b/src/antares/service/api_services/study_api.py @@ -16,19 +16,19 @@ from antares.api_conf.request_wrapper import RequestWrapper from antares.exceptions.exceptions import ( APIError, - StudySettingsUpdateError, BindingConstraintDeletionError, StudyDeletionError, + StudySettingsUpdateError, ) from antares.model.binding_constraint import BindingConstraint from antares.model.settings import ( - StudySettings, - GeneralProperties, - ThematicTrimming, - TimeSeriesProperties, AdequacyPatchProperties, AdvancedProperties, + GeneralProperties, OptimizationProperties, + StudySettings, + ThematicTrimming, + TimeSeriesProperties, ) from antares.service.base_services import BaseStudyService diff --git a/src/antares/service/api_services/thermal_api.py b/src/antares/service/api_services/thermal_api.py index 013e86e6..674e791a 100644 --- a/src/antares/service/api_services/thermal_api.py +++ b/src/antares/service/api_services/thermal_api.py @@ -16,8 +16,8 @@ from antares.api_conf.api_conf import APIconf from antares.api_conf.request_wrapper import RequestWrapper -from antares.exceptions.exceptions import APIError, ThermalPropertiesUpdateError, ThermalMatrixDownloadError -from antares.model.thermal import ThermalCluster, ThermalClusterProperties, ThermalClusterMatrixName +from antares.exceptions.exceptions import APIError, ThermalMatrixDownloadError, ThermalPropertiesUpdateError +from antares.model.thermal import ThermalCluster, ThermalClusterMatrixName, ThermalClusterProperties from antares.service.api_services.utils import get_matrix from antares.service.base_services import BaseThermalService diff --git a/src/antares/service/base_services.py b/src/antares/service/base_services.py index 4d83f674..374fa44e 100644 --- a/src/antares/service/base_services.py +++ b/src/antares/service/base_services.py @@ -12,28 +12,28 @@ from abc import ABC, abstractmethod from types import MappingProxyType -from typing import Optional, Dict, List +from typing import Dict, List, Optional import pandas as pd from antares.config.base_configuration import BaseConfiguration -from antares.model.area import AreaProperties, Area, AreaUi +from antares.model.area import Area, AreaProperties, AreaUi from antares.model.binding_constraint import ( - BindingConstraintProperties, - ConstraintTerm, BindingConstraint, + BindingConstraintProperties, ConstraintMatrixName, + ConstraintTerm, ) -from antares.model.hydro import HydroProperties, HydroMatrixName, Hydro -from antares.model.link import LinkProperties, LinkUi, Link +from antares.model.hydro import Hydro, HydroMatrixName, HydroProperties +from antares.model.link import Link, LinkProperties, LinkUi from antares.model.load import Load from antares.model.misc_gen import MiscGen -from antares.model.renewable import RenewableClusterProperties, RenewableCluster +from antares.model.renewable import RenewableCluster, RenewableClusterProperties from antares.model.reserves import Reserves from antares.model.settings import StudySettings from antares.model.solar import Solar -from antares.model.st_storage import STStorageProperties, STStorage -from antares.model.thermal import ThermalClusterProperties, ThermalCluster, ThermalClusterMatrixName +from antares.model.st_storage import STStorage, STStorageProperties +from antares.model.thermal import ThermalCluster, ThermalClusterMatrixName, ThermalClusterProperties from antares.model.wind import Wind diff --git a/src/antares/service/local_services/area_local.py b/src/antares/service/local_services/area_local.py index b2029857..c6b41593 100644 --- a/src/antares/service/local_services/area_local.py +++ b/src/antares/service/local_services/area_local.py @@ -12,30 +12,31 @@ import logging import os + from configparser import ConfigParser -from typing import Optional, Dict, List, Any +from typing import Any, Dict, List, Optional import pandas as pd from antares.config.local_configuration import LocalConfiguration from antares.exceptions.exceptions import CustomError -from antares.model.area import AreaProperties, AreaUi, Area, AreaPropertiesLocal, AreaUiLocal -from antares.model.hydro import HydroProperties, HydroMatrixName, Hydro, HydroPropertiesLocal +from antares.model.area import Area, AreaProperties, AreaPropertiesLocal, AreaUi, AreaUiLocal +from antares.model.hydro import Hydro, HydroMatrixName, HydroProperties, HydroPropertiesLocal from antares.model.load import Load from antares.model.misc_gen import MiscGen -from antares.model.renewable import RenewableClusterProperties, RenewableCluster, RenewableClusterPropertiesLocal +from antares.model.renewable import RenewableCluster, RenewableClusterProperties, RenewableClusterPropertiesLocal from antares.model.reserves import Reserves from antares.model.solar import Solar -from antares.model.st_storage import STStorageProperties, STStorage, STStoragePropertiesLocal -from antares.model.thermal import ThermalClusterProperties, ThermalCluster, ThermalClusterPropertiesLocal +from antares.model.st_storage import STStorage, STStorageProperties, STStoragePropertiesLocal +from antares.model.thermal import ThermalCluster, ThermalClusterProperties, ThermalClusterPropertiesLocal from antares.model.wind import Wind from antares.service.base_services import ( BaseAreaService, + BaseRenewableService, BaseShortTermStorageService, BaseThermalService, - BaseRenewableService, ) -from antares.tools.ini_tool import IniFileTypes, IniFile +from antares.tools.ini_tool import IniFile, IniFileTypes from antares.tools.time_series_tool import TimeSeriesFile, TimeSeriesFileType diff --git a/src/antares/service/local_services/binding_constraint_local.py b/src/antares/service/local_services/binding_constraint_local.py index c6b67aec..e0b99e23 100644 --- a/src/antares/service/local_services/binding_constraint_local.py +++ b/src/antares/service/local_services/binding_constraint_local.py @@ -10,23 +10,23 @@ # # This file is part of the Antares project. -from typing import Optional, Any +from typing import Any, Optional import numpy as np import pandas as pd from antares.config.local_configuration import LocalConfiguration from antares.model.binding_constraint import ( - BindingConstraintProperties, - ConstraintTerm, BindingConstraint, - ConstraintMatrixName, - BindingConstraintOperator, BindingConstraintFrequency, + BindingConstraintOperator, + BindingConstraintProperties, + ConstraintMatrixName, + ConstraintTerm, ) from antares.service.base_services import BaseBindingConstraintService from antares.tools.ini_tool import IniFile, IniFileTypes -from antares.tools.time_series_tool import TimeSeriesFile, TimeSeriesFileType, TimeSeries +from antares.tools.time_series_tool import TimeSeries, TimeSeriesFile, TimeSeriesFileType class BindingConstraintLocalService(BaseBindingConstraintService): diff --git a/src/antares/service/local_services/link_local.py b/src/antares/service/local_services/link_local.py index b0f03601..525be6f1 100644 --- a/src/antares/service/local_services/link_local.py +++ b/src/antares/service/local_services/link_local.py @@ -12,13 +12,14 @@ import configparser import os + from types import MappingProxyType -from typing import Optional, Any, Dict +from typing import Any, Dict, Optional from antares.config.local_configuration import LocalConfiguration -from antares.exceptions.exceptions import LinkCreationError, CustomError +from antares.exceptions.exceptions import CustomError, LinkCreationError from antares.model.area import Area -from antares.model.link import LinkProperties, LinkUi, Link, LinkPropertiesLocal, LinkUiLocal +from antares.model.link import Link, LinkProperties, LinkPropertiesLocal, LinkUi, LinkUiLocal from antares.service.base_services import BaseLinkService from antares.tools.contents_tool import sort_ini_sections diff --git a/src/antares/service/local_services/study_local.py b/src/antares/service/local_services/study_local.py index faa338d1..244aa9cc 100644 --- a/src/antares/service/local_services/study_local.py +++ b/src/antares/service/local_services/study_local.py @@ -10,7 +10,7 @@ # # This file is part of the Antares project. -from typing import Optional, Any +from typing import Any, Optional from antares.config.local_configuration import LocalConfiguration from antares.model.binding_constraint import BindingConstraint diff --git a/src/antares/service/service_factory.py b/src/antares/service/service_factory.py index a5416b86..e8de5b3b 100644 --- a/src/antares/service/service_factory.py +++ b/src/antares/service/service_factory.py @@ -22,12 +22,12 @@ from antares.service.api_services.thermal_api import ThermalApiService from antares.service.base_services import ( BaseAreaService, - BaseLinkService, - BaseThermalService, BaseBindingConstraintService, - BaseStudyService, + BaseLinkService, BaseRenewableService, BaseShortTermStorageService, + BaseStudyService, + BaseThermalService, ) from antares.service.local_services.area_local import AreaLocalService from antares.service.local_services.binding_constraint_local import BindingConstraintLocalService diff --git a/src/antares/tools/all_optional_meta.py b/src/antares/tools/all_optional_meta.py index 6901566b..9aa394e3 100644 --- a/src/antares/tools/all_optional_meta.py +++ b/src/antares/tools/all_optional_meta.py @@ -12,6 +12,7 @@ import copy import typing as t + from pydantic import BaseModel, create_model ModelClass = t.TypeVar("ModelClass", bound=BaseModel) diff --git a/src/antares/tools/contents_tool.py b/src/antares/tools/contents_tool.py index a3d78184..5cc04367 100644 --- a/src/antares/tools/contents_tool.py +++ b/src/antares/tools/contents_tool.py @@ -13,6 +13,7 @@ import configparser import json import re + from enum import Enum from pathlib import Path from typing import Any, Dict, Optional diff --git a/src/antares/tools/ini_tool.py b/src/antares/tools/ini_tool.py index eac41b1f..42f233aa 100644 --- a/src/antares/tools/ini_tool.py +++ b/src/antares/tools/ini_tool.py @@ -13,7 +13,7 @@ from configparser import ConfigParser from enum import Enum from pathlib import Path -from typing import Optional, Any, overload, Union +from typing import Any, Optional, Union, overload class IniFileTypes(Enum): diff --git a/src/antares/tools/prepro_folder.py b/src/antares/tools/prepro_folder.py index 8896f452..79df4d19 100644 --- a/src/antares/tools/prepro_folder.py +++ b/src/antares/tools/prepro_folder.py @@ -15,8 +15,8 @@ import numpy as np import pandas as pd -from antares.tools.ini_tool import IniFileTypes, IniFile -from antares.tools.time_series_tool import TimeSeriesFileType, TimeSeries, TimeSeriesFile +from antares.tools.ini_tool import IniFile, IniFileTypes +from antares.tools.time_series_tool import TimeSeries, TimeSeriesFile, TimeSeriesFileType class PreproFolder: diff --git a/tests/antares/delete/test_delete_api.py b/tests/antares/delete/test_delete_api.py index 954372a4..c19d64f9 100644 --- a/tests/antares/delete/test_delete_api.py +++ b/tests/antares/delete/test_delete_api.py @@ -16,12 +16,12 @@ from antares.api_conf.api_conf import APIconf from antares.exceptions.exceptions import ( AreaDeletionError, + BindingConstraintDeletionError, + ConstraintTermDeletionError, LinkDeletionError, - ThermalDeletionError, RenewableDeletionError, STStorageDeletionError, - BindingConstraintDeletionError, - ConstraintTermDeletionError, + ThermalDeletionError, ) from antares.model.area import Area from antares.model.binding_constraint import BindingConstraint diff --git a/tests/antares/services/api_services/test_area_api.py b/tests/antares/services/api_services/test_area_api.py index d87a2dc0..587668d4 100644 --- a/tests/antares/services/api_services/test_area_api.py +++ b/tests/antares/services/api_services/test_area_api.py @@ -11,28 +11,29 @@ # This file is part of the Antares project. +import pytest +import requests_mock + +import numpy as np +import pandas as pd + from antares.api_conf.api_conf import APIconf from antares.exceptions.exceptions import ( - ThermalCreationError, - RenewableCreationError, - STStorageCreationError, AreaPropertiesUpdateError, AreaUiUpdateError, LoadMatrixDownloadError, LoadMatrixUploadError, MatrixUploadError, + RenewableCreationError, + STStorageCreationError, + ThermalCreationError, ) -from antares.model.area import Area, AreaUi, AreaProperties -from antares.model.hydro import HydroMatrixName, HydroProperties, Hydro -from antares.model.renewable import RenewableClusterProperties, RenewableCluster -from antares.model.st_storage import STStorageProperties, STStorage -from antares.model.thermal import ThermalClusterProperties, ThermalCluster +from antares.model.area import Area, AreaProperties, AreaUi +from antares.model.hydro import Hydro, HydroMatrixName, HydroProperties +from antares.model.renewable import RenewableCluster, RenewableClusterProperties +from antares.model.st_storage import STStorage, STStorageProperties +from antares.model.thermal import ThermalCluster, ThermalClusterProperties from antares.service.service_factory import ServiceFactory -import requests_mock - -import pytest -import pandas as pd -import numpy as np class TestCreateAPI: diff --git a/tests/antares/services/api_services/test_binding_constraint_api.py b/tests/antares/services/api_services/test_binding_constraint_api.py index 4fcbb5da..3577d459 100644 --- a/tests/antares/services/api_services/test_binding_constraint_api.py +++ b/tests/antares/services/api_services/test_binding_constraint_api.py @@ -10,17 +10,17 @@ # # This file is part of the Antares project. +import pytest +import requests_mock + import pandas as pd from antares.api_conf.api_conf import APIconf -from antares.exceptions.exceptions import ConstraintPropertiesUpdateError, ConstraintMatrixDownloadError +from antares.exceptions.exceptions import ConstraintMatrixDownloadError, ConstraintPropertiesUpdateError from antares.model.area import Area -from antares.model.binding_constraint import BindingConstraintProperties, BindingConstraint, ConstraintMatrixName +from antares.model.binding_constraint import BindingConstraint, BindingConstraintProperties, ConstraintMatrixName from antares.model.study import Study from antares.service.service_factory import ServiceFactory -import requests_mock - -import pytest @pytest.fixture diff --git a/tests/antares/services/api_services/test_link_api.py b/tests/antares/services/api_services/test_link_api.py index ddc5bed8..dbfd0f37 100644 --- a/tests/antares/services/api_services/test_link_api.py +++ b/tests/antares/services/api_services/test_link_api.py @@ -15,10 +15,10 @@ import requests_mock from antares.api_conf.api_conf import APIconf -from antares.exceptions.exceptions import LinkUiUpdateError, LinkPropertiesUpdateError +from antares.exceptions.exceptions import LinkPropertiesUpdateError, LinkUiUpdateError from antares.model.area import Area from antares.model.commons import FilterOption -from antares.model.link import LinkProperties, LinkUi, Link +from antares.model.link import Link, LinkProperties, LinkUi from antares.model.study import Study from antares.service.service_factory import ServiceFactory diff --git a/tests/antares/services/api_services/test_renewable_api.py b/tests/antares/services/api_services/test_renewable_api.py index 80e7f3c8..28d86720 100644 --- a/tests/antares/services/api_services/test_renewable_api.py +++ b/tests/antares/services/api_services/test_renewable_api.py @@ -10,16 +10,16 @@ # # This file is part of the Antares project. +import pytest +import requests_mock + import pandas as pd from antares.api_conf.api_conf import APIconf -from antares.exceptions.exceptions import RenewablePropertiesUpdateError, RenewableMatrixDownloadError +from antares.exceptions.exceptions import RenewableMatrixDownloadError, RenewablePropertiesUpdateError from antares.model.area import Area -from antares.model.renewable import RenewableClusterProperties, RenewableCluster +from antares.model.renewable import RenewableCluster, RenewableClusterProperties from antares.service.service_factory import ServiceFactory -import requests_mock - -import pytest class TestCreateAPI: diff --git a/tests/antares/services/api_services/test_st_storage_api.py b/tests/antares/services/api_services/test_st_storage_api.py index e9ae2d5f..e665b12a 100644 --- a/tests/antares/services/api_services/test_st_storage_api.py +++ b/tests/antares/services/api_services/test_st_storage_api.py @@ -10,20 +10,20 @@ # # This file is part of the Antares project. +import pytest +import requests_mock + import pandas as pd from antares.api_conf.api_conf import APIconf from antares.exceptions.exceptions import ( - STStoragePropertiesUpdateError, STStorageMatrixDownloadError, STStorageMatrixUploadError, + STStoragePropertiesUpdateError, ) from antares.model.area import Area from antares.model.st_storage import STStorage, STStorageProperties from antares.service.service_factory import ServiceFactory -import requests_mock - -import pytest class TestCreateAPI: diff --git a/tests/antares/services/api_services/test_study_api.py b/tests/antares/services/api_services/test_study_api.py index a2b46ae4..c979a8ec 100644 --- a/tests/antares/services/api_services/test_study_api.py +++ b/tests/antares/services/api_services/test_study_api.py @@ -11,24 +11,24 @@ # This file is part of the Antares project. -from antares.api_conf.api_conf import APIconf +import pytest import requests_mock -import re -import pytest +import re +from antares.api_conf.api_conf import APIconf from antares.exceptions.exceptions import ( - StudyCreationError, - BindingConstraintCreationError, AreaCreationError, + BindingConstraintCreationError, LinkCreationError, + StudyCreationError, StudySettingsUpdateError, ) -from antares.model.area import AreaUi, AreaProperties, Area -from antares.model.binding_constraint import BindingConstraintProperties, BindingConstraint -from antares.model.link import LinkProperties, LinkUi, Link -from antares.model.settings import StudySettings, GeneralProperties -from antares.model.study import create_study_api, Study +from antares.model.area import Area, AreaProperties, AreaUi +from antares.model.binding_constraint import BindingConstraint, BindingConstraintProperties +from antares.model.link import Link, LinkProperties, LinkUi +from antares.model.settings import GeneralProperties, StudySettings +from antares.model.study import Study, create_study_api from antares.service.service_factory import ServiceFactory diff --git a/tests/antares/services/api_services/test_thermal_api.py b/tests/antares/services/api_services/test_thermal_api.py index f3654150..22ab05b3 100644 --- a/tests/antares/services/api_services/test_thermal_api.py +++ b/tests/antares/services/api_services/test_thermal_api.py @@ -10,17 +10,17 @@ # # This file is part of the Antares project. +import pytest +import requests_mock + import pandas as pd from antares.api_conf.api_conf import APIconf -from antares.exceptions.exceptions import ThermalPropertiesUpdateError, ThermalMatrixDownloadError +from antares.exceptions.exceptions import ThermalMatrixDownloadError, ThermalPropertiesUpdateError from antares.model.area import Area from antares.model.study import Study -from antares.model.thermal import ThermalCluster, ThermalClusterProperties, ThermalClusterMatrixName +from antares.model.thermal import ThermalCluster, ThermalClusterMatrixName, ThermalClusterProperties from antares.service.service_factory import ServiceFactory -import requests_mock - -import pytest @pytest.fixture diff --git a/tests/antares/services/local_services/conftest.py b/tests/antares/services/local_services/conftest.py index 1570e33f..6ed105e4 100644 --- a/tests/antares/services/local_services/conftest.py +++ b/tests/antares/services/local_services/conftest.py @@ -16,21 +16,21 @@ from antares.model.area import Area from antares.model.binding_constraint import ( BindingConstraint, - BindingConstraintProperties, BindingConstraintFrequency, BindingConstraintOperator, + BindingConstraintProperties, ) from antares.model.hydro import HydroProperties from antares.model.load import Load -from antares.model.renewable import RenewableClusterProperties, TimeSeriesInterpretation, RenewableClusterGroup +from antares.model.renewable import RenewableClusterGroup, RenewableClusterProperties, TimeSeriesInterpretation from antares.model.solar import Solar -from antares.model.st_storage import STStorageProperties, STStorageGroup +from antares.model.st_storage import STStorageGroup, STStorageProperties from antares.model.study import Study, create_study_local from antares.model.thermal import ( - ThermalClusterProperties, + LawOption, LocalTSGenerationBehavior, ThermalClusterGroup, - LawOption, + ThermalClusterProperties, ThermalCostGeneration, ) from antares.model.wind import Wind diff --git a/tests/antares/services/local_services/test_area.py b/tests/antares/services/local_services/test_area.py index 38f93680..f5de2aab 100644 --- a/tests/antares/services/local_services/test_area.py +++ b/tests/antares/services/local_services/test_area.py @@ -18,23 +18,23 @@ from antares.model.hydro import Hydro from antares.model.renewable import ( - RenewableClusterProperties, RenewableCluster, RenewableClusterGroup, - TimeSeriesInterpretation, + RenewableClusterProperties, RenewableClusterPropertiesLocal, + TimeSeriesInterpretation, ) -from antares.model.st_storage import STStorage, STStoragePropertiesLocal, STStorageProperties, STStorageGroup +from antares.model.st_storage import STStorage, STStorageGroup, STStorageProperties, STStoragePropertiesLocal from antares.model.thermal import ( + LawOption, + LocalTSGenerationBehavior, ThermalCluster, - ThermalClusterProperties, ThermalClusterGroup, - LocalTSGenerationBehavior, - LawOption, - ThermalCostGeneration, + ThermalClusterProperties, ThermalClusterPropertiesLocal, + ThermalCostGeneration, ) -from antares.tools.ini_tool import IniFileTypes, IniFile +from antares.tools.ini_tool import IniFile, IniFileTypes from antares.tools.time_series_tool import TimeSeriesFileType diff --git a/tests/antares/services/local_services/test_study.py b/tests/antares/services/local_services/test_study.py index 15be72cc..da85fce8 100644 --- a/tests/antares/services/local_services/test_study.py +++ b/tests/antares/services/local_services/test_study.py @@ -10,38 +10,40 @@ # # This file is part of the Antares project. +import pytest + import logging import os import time + from configparser import ConfigParser from pathlib import Path import numpy as np import pandas as pd -import pytest from antares.config.local_configuration import LocalConfiguration from antares.exceptions.exceptions import CustomError, LinkCreationError -from antares.model.area import AreaProperties, AreaUi, AreaUiLocal, AreaPropertiesLocal, Area +from antares.model.area import Area, AreaProperties, AreaPropertiesLocal, AreaUi, AreaUiLocal from antares.model.binding_constraint import ( BindingConstraint, - BindingConstraintProperties, BindingConstraintFrequency, BindingConstraintOperator, - ConstraintTerm, + BindingConstraintProperties, BindingConstraintPropertiesLocal, + ConstraintTerm, ) from antares.model.commons import FilterOption from antares.model.hydro import Hydro from antares.model.link import ( + AssetType, Link, LinkProperties, LinkPropertiesLocal, - TransmissionCapacities, - LinkUi, - AssetType, LinkStyle, + LinkUi, LinkUiLocal, + TransmissionCapacities, ) from antares.model.study import create_study_local from antares.service.local_services.area_local import AreaLocalService diff --git a/tests/antares/tools/conftest.py b/tests/antares/tools/conftest.py index 3807bd0b..ccbb86ae 100644 --- a/tests/antares/tools/conftest.py +++ b/tests/antares/tools/conftest.py @@ -10,9 +10,10 @@ # # This file is part of the Antares project. +import pytest + import numpy as np import pandas as pd -import pytest from antares.tools.time_series_tool import TimeSeriesFile, TimeSeriesFileType diff --git a/tests/antares/tools/test_time_series_tool.py b/tests/antares/tools/test_time_series_tool.py index e2f64f6d..e52bf512 100644 --- a/tests/antares/tools/test_time_series_tool.py +++ b/tests/antares/tools/test_time_series_tool.py @@ -10,9 +10,10 @@ # # This file is part of the Antares project. +import pytest + import numpy as np import pandas as pd -import pytest from antares.tools.time_series_tool import TimeSeries, TimeSeriesFile, TimeSeriesFileType diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 00000000..befa122e --- /dev/null +++ b/tests/integration/__init__.py @@ -0,0 +1,12 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You 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/antares_web_desktop.py b/tests/integration/antares_web_desktop.py index 39733640..48de006e 100644 --- a/tests/integration/antares_web_desktop.py +++ b/tests/integration/antares_web_desktop.py @@ -13,6 +13,7 @@ import socket import subprocess import time + from pathlib import Path import requests diff --git a/tests/integration/test_web_client.py b/tests/integration/test_web_client.py index 424900dc..81a4ff75 100644 --- a/tests/integration/test_web_client.py +++ b/tests/integration/test_web_client.py @@ -9,30 +9,31 @@ # SPDX-License-Identifier: MPL-2.0 # # This file is part of the Antares project. +import pytest + import numpy as np import pandas as pd -import pytest from antares.api_conf.api_conf import APIconf from antares.exceptions.exceptions import ( - LoadMatrixUploadError, - STStorageMatrixUploadError, + AreaDeletionError, BindingConstraintCreationError, ConstraintMatrixUpdateError, - AreaDeletionError, + LoadMatrixUploadError, + STStorageMatrixUploadError, ) -from antares.model.settings.advanced_parameters import UnitCommitmentMode, AdvancedProperties -from antares.model.study import create_study_api -from antares.model.binding_constraint import BindingConstraintProperties, LinkData, ClusterData, ConstraintTerm -from antares.model.link import LinkUi, LinkProperties, LinkStyle -from antares.model.renewable import RenewableClusterProperties, RenewableClusterGroup, TimeSeriesInterpretation -from antares.model.settings import StudySettings, GeneralProperties, PlaylistData +from antares.model.area import AdequacyPatchMode, AreaProperties, AreaUi, FilterOption +from antares.model.binding_constraint import BindingConstraintProperties, ClusterData, ConstraintTerm, LinkData +from antares.model.link import LinkProperties, LinkStyle, LinkUi +from antares.model.renewable import RenewableClusterGroup, RenewableClusterProperties, TimeSeriesInterpretation +from antares.model.settings import GeneralProperties, PlaylistData, StudySettings +from antares.model.settings.advanced_parameters import AdvancedProperties, UnitCommitmentMode from antares.model.settings.general import Mode -from antares.model.st_storage import STStorageProperties, STStorageGroup, STStorageMatrixName -from antares.model.thermal import ThermalClusterProperties, ThermalClusterGroup +from antares.model.st_storage import STStorageGroup, STStorageMatrixName, STStorageProperties +from antares.model.study import create_study_api +from antares.model.thermal import ThermalClusterGroup, ThermalClusterProperties -from antares.model.area import AreaUi, AreaProperties, AdequacyPatchMode, FilterOption -from tests.integration.antares_web_desktop import AntaresWebDesktop +from integration.antares_web_desktop import AntaresWebDesktop # todo add integration tests for matrices diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..62bb20e5 --- /dev/null +++ b/tox.ini @@ -0,0 +1,24 @@ +[tox] +env_list = + py3.{9,10,11,12}-test + lint + +[testenv] +deps = + -r requirements-dev.txt + +[testenv:py3.{9,10,11,12}-test] +description = run the tests with pytest +commands = + pytest tests/antares {posargs} + +[testenv:lint] +description = linting with ruff +extras = lint +commands = + python scripts/license_checker_and_adder.py --path=src --action=fix + python scripts/license_checker_and_adder.py --path=tests --action=fix + ruff check --fix src/ tests/ {posargs} + ruff format src/ tests/ {posargs} + mypy {posargs} +