From 13026d98ce1f336946a599c2bcccd95d11b63661 Mon Sep 17 00:00:00 2001 From: Fabrice Normandin Date: Tue, 14 Mar 2023 14:06:07 -0400 Subject: [PATCH] Simplify the CLI code and make help prettier Fixes #34 Signed-off-by: Fabrice Normandin --- sarc/cli/__init__.py | 66 ++++++++++++++++++++------------- sarc/cli/acquire/__init__.py | 30 ++++++++------- sarc/cli/acquire/allocations.py | 2 + sarc/cli/acquire/jobs.py | 3 ++ sarc/cli/acquire/storages.py | 6 ++- sarc/cli/db/__init__.py | 24 +++++------- sarc/cli/db/init.py | 2 + 7 files changed, 77 insertions(+), 56 deletions(-) diff --git a/sarc/cli/__init__.py b/sarc/cli/__init__.py index 4349434f..8e7cb583 100644 --- a/sarc/cli/__init__.py +++ b/sarc/cli/__init__.py @@ -1,49 +1,65 @@ from __future__ import annotations import logging -from dataclasses import dataclass -from typing import Any, Union +from typing import Protocol +from simple_parsing import ArgumentParser -from simple_parsing import ArgumentParser, field, subparsers +from sarc.cli.db import add_db_commands +from sarc.cli.acquire import add_acquire_commands -from sarc.cli.acquire import Acquire -from sarc.cli.db import Db logger = logging.getLogger(__name__) -@dataclass -class CLI: - command: Union[Acquire, Db] = subparsers({"acquire": Acquire, "db": Db}) +class Command(Protocol): + def execute(self) -> int: + ... + + +def main(argv: list[str] | None = None) -> int: + parser = ArgumentParser(prog="test") + # parser.add_arguments(GlobalArgs, dest="global_args") - verbose: int = field( - alias=["-v"], + parser.add_argument( + "-v", + "--verbose", default=0, - help="logging levels of information about the process (-v: INFO. -vv: DEBUG)", action="count", + help="logging levels of information about the process (-v: INFO. -vv: DEBUG)", ) - def execute(self) -> int: - levels = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG} + command_subparsers = parser.add_subparsers( + dest="command_name", + title="Command title", + description="Description", + required=True, + ) - logging.basicConfig( - format="%(asctime)-15s::%(levelname)s::%(name)s::%(message)s", - level=levels.get(self.verbose, logging.DEBUG), - ) + db_parser = command_subparsers.add_parser("db", help="database-related commands") - # logger.debug("SARC version : %s", sarc.__version__) + add_db_commands(db_parser) - return self.command.execute() + acquire_parser = command_subparsers.add_parser( + "acquire", help="commands used acquire different kinds of data" + ) + add_acquire_commands(acquire_parser) -def main(argv: list[Any] | None = None) -> int: - """Main commandline for SARC""" - parser = ArgumentParser() - parser.add_arguments(CLI, dest="command") args = parser.parse_args(argv) - command: CLI = args.command - return command.execute() + verbose: int = args.verbose + # NOTE: unused, but available in case it's needed: + # command_name: str = args.command_name + # subcommand_name: str = args.subcommand_name + subcommand: Command = args.subcommand + + levels = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG} + logging.basicConfig( + format="%(asctime)-15s::%(levelname)s::%(name)s::%(message)s", + level=levels.get(verbose, logging.DEBUG), + ) + + return subcommand.execute() if __name__ == "__main__": diff --git a/sarc/cli/acquire/__init__.py b/sarc/cli/acquire/__init__.py index 598309d9..b9164158 100644 --- a/sarc/cli/acquire/__init__.py +++ b/sarc/cli/acquire/__init__.py @@ -1,22 +1,24 @@ -from dataclasses import dataclass -from typing import Union - -from simple_parsing import subparsers +from simple_parsing import ArgumentParser from sarc.cli.acquire.allocations import AcquireAllocations from sarc.cli.acquire.jobs import AcquireJobs from sarc.cli.acquire.storages import AcquireStorages -@dataclass -class Acquire: - command: Union[AcquireAllocations, AcquireJobs, AcquireStorages] = subparsers( - { - "allocations": AcquireAllocations, - "jobs": AcquireJobs, - "storages": AcquireStorages, - } +def add_acquire_commands(parser: ArgumentParser): + subparsers = parser.add_subparsers( + title="subcommand", + description="Acquire subcommand", + dest="subcommand_name", + required=True, + ) + allocations_parser = subparsers.add_parser( + "allocations", help="Acquire allocations help" ) + allocations_parser.add_arguments(AcquireAllocations, dest="subcommand") + + jobs_parser = subparsers.add_parser("jobs", help="Acquire jobs help") + jobs_parser.add_arguments(AcquireJobs, dest="subcommand") - def execute(self) -> int: - return self.command.execute() + storages_parser = subparsers.add_parser("storages", help="Acquire storages help") + storages_parser.add_arguments(AcquireStorages, dest="subcommand") diff --git a/sarc/cli/acquire/allocations.py b/sarc/cli/acquire/allocations.py index 9004d4bb..fe670c0d 100644 --- a/sarc/cli/acquire/allocations.py +++ b/sarc/cli/acquire/allocations.py @@ -57,6 +57,8 @@ def convert_csv_row_to_allocation( @dataclass class AcquireAllocations: + """Command to acquire data about the allocations.""" + file: Path def execute(self) -> int: diff --git a/sarc/cli/acquire/jobs.py b/sarc/cli/acquire/jobs.py index aed4da77..73dd9fff 100644 --- a/sarc/cli/acquire/jobs.py +++ b/sarc/cli/acquire/jobs.py @@ -38,9 +38,12 @@ def _daterange( @dataclass class AcquireJobs: + """Command used to acquire job data.""" + cluster_names: list[str] = field( alias=["-c"], default_factory=list, choices=clusters ) + """List of cluster names to acquire job data for.""" dates: list[str] = field(alias=["-d"], default_factory=list) diff --git a/sarc/cli/acquire/storages.py b/sarc/cli/acquire/storages.py index 48ffa559..6a100882 100644 --- a/sarc/cli/acquire/storages.py +++ b/sarc/cli/acquire/storages.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from pathlib import Path - +from typing import Optional from simple_parsing import field from sarc.cli.utils import clusters @@ -15,7 +15,9 @@ @dataclass class AcquireStorages: - file: Path = field(default=None) + """Acquire information about the storage.""" + + file: Optional[Path] = None cluster_names: list[str] = field( alias=["-c"], default_factory=list, choices=clusters ) diff --git a/sarc/cli/db/__init__.py b/sarc/cli/db/__init__.py index a5308283..6ad2a8c6 100644 --- a/sarc/cli/db/__init__.py +++ b/sarc/cli/db/__init__.py @@ -1,20 +1,14 @@ -from dataclasses import dataclass -from typing import Union - -from simple_parsing import subparsers +from simple_parsing import ArgumentParser from sarc.cli.db.init import DbInit -@dataclass -class Db: - """this is help""" - - command: Union[DbInit] = subparsers( - { - "init": DbInit, - } +def add_db_commands(parser: ArgumentParser): + subparsers = parser.add_subparsers( + title="subcommand", + description="subcommand description", + dest="subcommand_name", + required=True, ) - - def execute(self) -> int: - return self.command.execute() + db_init_subparser = subparsers.add_parser("init", help="Initialize the DB") + db_init_subparser.add_arguments(DbInit, dest="subcommand") diff --git a/sarc/cli/db/init.py b/sarc/cli/db/init.py index 2b61bbce..a88c4ce9 100644 --- a/sarc/cli/db/init.py +++ b/sarc/cli/db/init.py @@ -11,6 +11,8 @@ @dataclass class DbInit: + """Initializes the database.""" + url: Optional[str] database: Optional[str]