-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add the show, create and upgrade applications
- Loading branch information
1 parent
54a5f6c
commit 5e921f7
Showing
90 changed files
with
2,496 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
""" | ||
Main entrypoint for the CLI application. | ||
""" | ||
|
||
import sys | ||
|
||
from antares.study.version.cli import cli | ||
|
||
|
||
def main(): | ||
cli(sys.argv[1:]) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
""" | ||
The CLI module for the study version. | ||
This module defines the following CLI commands: | ||
- antares-study-version show: display the details of a study in human-readable format (name, version, creation date, etc.) | ||
- antares-study-version create: create a new study. | ||
""" | ||
|
||
import click | ||
|
||
from antares.study.version.__about__ import __date__, __version__ | ||
from antares.study.version.create_app import CreateApp, available_versions | ||
from antares.study.version.exceptions import ApplicationError | ||
from antares.study.version.show_app import ShowApp | ||
from antares.study.version.upgrade_app import UpgradeApp | ||
|
||
INTERRUPTED_BY_THE_USER = "Operation interrupted by the user." | ||
|
||
|
||
@click.group(context_settings={"max_content_width": 120}) | ||
@click.version_option(package_name="antares-study-version", message=f"v{__version__} ({__date__})") | ||
def cli() -> None: | ||
""" | ||
Main entrypoint for the CLI application. | ||
""" | ||
|
||
|
||
@cli.command() | ||
@click.argument( | ||
"study_dir", | ||
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True), | ||
) | ||
def show(study_dir: str) -> None: | ||
""" | ||
Display the details of a study in human-readable format. | ||
STUDY_DIR: The directory containing the study. | ||
""" | ||
try: | ||
app = ShowApp(study_dir) # type: ignore | ||
except (ValueError, FileNotFoundError) as e: | ||
click.echo(f"Error: {e}", err=True) | ||
raise click.Abort() | ||
|
||
try: | ||
app() | ||
except ApplicationError as e: | ||
click.echo(f"Error: {e}", err=True) | ||
raise click.Abort() | ||
except KeyboardInterrupt: | ||
click.echo(INTERRUPTED_BY_THE_USER, err=True) | ||
raise click.Abort() | ||
|
||
|
||
def _display_available_versions(ctx: click.Context, _param: click.Option, value: bool) -> None: | ||
if not value or ctx.resilient_parsing: | ||
return | ||
click.echo(f"Available versions: {', '.join(available_versions())}") | ||
ctx.exit() | ||
|
||
|
||
@cli.command() | ||
@click.argument( | ||
"study_dir", | ||
type=click.Path(exists=False, file_okay=False, dir_okay=True, resolve_path=True), | ||
) | ||
@click.option( | ||
"-c", | ||
"--caption", | ||
default="New Study", | ||
help="Caption of the study", | ||
show_default=True, | ||
) | ||
@click.option( | ||
"-v", | ||
"--version", | ||
default=available_versions()[-1], | ||
help="Version of the study to create", | ||
show_default=True, | ||
type=click.Choice(available_versions()), | ||
) | ||
@click.option( | ||
"-a", | ||
"--author", | ||
default="Anonymous", | ||
help="Author of the study", | ||
show_default=True, | ||
) | ||
@click.option( | ||
"--versions", | ||
is_flag=True, | ||
callback=_display_available_versions, | ||
expose_value=False, | ||
is_eager=True, | ||
help="Display all available upgrade versions and quit.", | ||
) | ||
def create(study_dir: str, caption: str, version: str, author: str) -> None: | ||
""" | ||
Create a new study in the specified directory. | ||
STUDY_DIR: The directory where the study will be created. | ||
""" | ||
try: | ||
app = CreateApp(study_dir, caption=caption, version=version, author=author) # type: ignore | ||
except (ValueError, FileExistsError) as e: | ||
click.echo(f"Error: {e}", err=True) | ||
raise click.Abort() | ||
|
||
try: | ||
app() | ||
except ApplicationError as e: | ||
click.echo(f"Error: {e}", err=True) | ||
raise click.Abort() | ||
except KeyboardInterrupt: | ||
click.echo(INTERRUPTED_BY_THE_USER, err=True) | ||
raise click.Abort() | ||
|
||
|
||
@cli.command() | ||
@click.argument( | ||
"study_dir", | ||
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True), | ||
) | ||
@click.option( | ||
"-v", | ||
"--version", | ||
default=available_versions()[-1], | ||
help="Version of the study to create", | ||
show_default=True, | ||
type=click.Choice(available_versions()), | ||
) | ||
def upgrade(study_dir: str, version: str) -> None: | ||
""" | ||
Upgrade a study to a new version. | ||
STUDY_DIR: The directory containing the study to upgrade. | ||
""" | ||
try: | ||
app = UpgradeApp(study_dir, version=version) # type: ignore | ||
except (ValueError, FileNotFoundError) as e: | ||
click.echo(f"Error: {e}", err=True) | ||
raise click.Abort() | ||
|
||
try: | ||
app() | ||
except ApplicationError as e: | ||
click.echo(f"Error: {e}", err=True) | ||
raise click.Abort() | ||
except KeyboardInterrupt: | ||
click.echo(INTERRUPTED_BY_THE_USER, err=True) | ||
raise click.Abort() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import dataclasses | ||
import datetime | ||
import typing as t | ||
import zipfile | ||
from importlib.resources import contents, open_binary | ||
from pathlib import Path | ||
|
||
from antares.study.version.exceptions import ApplicationError | ||
from antares.study.version.model.study_antares import StudyAntares | ||
from antares.study.version.model.study_version import StudyVersion | ||
|
||
_RESOURCES_PACKAGE = "antares.study.version.create_app.resources" | ||
|
||
|
||
def get_template_version(template_name: str) -> StudyVersion: | ||
template_name = template_name.replace(".zip", "") | ||
version_str = template_name.split("_")[-1] # 880.zip | ||
return StudyVersion.parse(version_str) | ||
|
||
|
||
TEMPLATES_BY_VERSIONS: t.Dict[StudyVersion, str] = { | ||
get_template_version(name): name for name in contents(_RESOURCES_PACKAGE) if name.endswith(".zip") | ||
} | ||
|
||
|
||
def available_versions() -> t.List[str]: | ||
""" | ||
Return a list of available template versions. | ||
Returns: | ||
A list of available template versions. | ||
""" | ||
return [f"{ver:2d}" for ver in sorted(TEMPLATES_BY_VERSIONS)] | ||
|
||
|
||
@dataclasses.dataclass | ||
class CreateApp: | ||
""" | ||
Create a new study. | ||
""" | ||
|
||
study_dir: Path | ||
caption: str | ||
version: StudyVersion | ||
author: str | ||
|
||
def __post_init__(self): | ||
self.study_dir = Path(self.study_dir) | ||
self.caption = self.caption.strip() | ||
self.version = StudyVersion.parse(self.version) | ||
self.author = self.author.strip() | ||
if self.study_dir.exists(): | ||
raise FileExistsError(f"Study directory already exists: '{self.study_dir}'") | ||
if not self.caption: | ||
raise ValueError("Caption cannot be empty") | ||
|
||
def __call__(self) -> None: | ||
try: | ||
template_name = TEMPLATES_BY_VERSIONS[self.version] | ||
except KeyError: | ||
msg = f"No available template for version {self.version}: available templates are {available_versions()}" | ||
raise ApplicationError(msg) | ||
print(f"Extracting template {template_name} to '{self.study_dir}'...") | ||
with open_binary(_RESOURCES_PACKAGE, template_name) as zip_file: | ||
with zipfile.ZipFile(zip_file, mode="r") as archive: | ||
archive.extractall(self.study_dir) | ||
|
||
creation_date = datetime.datetime.now() | ||
study_antares = StudyAntares( | ||
version=self.version, | ||
caption=self.caption, | ||
created_date=creation_date, | ||
last_save_date=creation_date, | ||
author=self.author, | ||
) | ||
print("Writing 'study.antares' file...") | ||
study_antares.to_ini_file(self.study_dir, update_save_date=False) | ||
print(f"Study '{self.caption}' created successfully.") |
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class ApplicationError(Exception): | ||
""" | ||
Base class for all exceptions raised by the application. | ||
""" |
Oops, something went wrong.