diff options
author | crupest <crupest@outlook.com> | 2024-11-11 01:12:29 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-01-08 22:37:23 +0800 |
commit | 43892b892cfdc4e15f7ab191c42ccb32279fd7f6 (patch) | |
tree | 9161420d397b95d24a0ac90629e0eab27f1b337f /tools/cru-py/cru/service/_base.py | |
parent | c3308421b665e5d8dcb70b78acf137541a026555 (diff) | |
download | crupest-43892b892cfdc4e15f7ab191c42ccb32279fd7f6.tar.gz crupest-43892b892cfdc4e15f7ab191c42ccb32279fd7f6.tar.bz2 crupest-43892b892cfdc4e15f7ab191c42ccb32279fd7f6.zip |
HALF WORK: 2024.1.8
Diffstat (limited to 'tools/cru-py/cru/service/_base.py')
-rw-r--r-- | tools/cru-py/cru/service/_base.py | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/tools/cru-py/cru/service/_base.py b/tools/cru-py/cru/service/_base.py index 98eed89..3b511a1 100644 --- a/tools/cru-py/cru/service/_base.py +++ b/tools/cru-py/cru/service/_base.py @@ -2,6 +2,8 @@ from __future__ import annotations from argparse import ArgumentParser, Namespace from abc import ABC, abstractmethod +import argparse +from collections.abc import Sequence import os from pathlib import Path from typing import TypeVar, overload @@ -12,6 +14,7 @@ _F = TypeVar("_F") OWNER_NAME = "crupest" + class InternalAppException(CruInternalError): pass @@ -153,7 +156,7 @@ class AppRootPath(AppPath): return self._app -class AppFeatureProvider: +class AppFeatureProvider(ABC): def __init__(self, name: str, /, app: AppBase | None = None): super().__init__() self._name = name @@ -168,15 +171,56 @@ class AppFeatureProvider: def name(self) -> str: return self._name + @abstractmethod + def setup(self) -> None: ... + + +class AppCommandFeatureProvider(AppFeatureProvider): + @abstractmethod + def get_command_info(self) -> tuple[str, str]: ... -class AppCommandFeatureProvider(AppFeatureProvider, ABC): @abstractmethod - def add_arg_parser(self, arg_parser: ArgumentParser) -> None: ... + def setup_arg_parser(self, arg_parser: ArgumentParser): ... @abstractmethod def run_command(self, args: Namespace) -> None: ... +DATA_DIR_NAME = "data" + + +class CommandDispatcher(AppFeatureProvider): + def __init__(self) -> None: + super().__init__("command-dispatcher") + + def _setup_arg_parser(self) -> None: + self._map: dict[str, AppCommandFeatureProvider] = {} + arg_parser = argparse.ArgumentParser(description="Service management") + subparsers = arg_parser.add_subparsers(dest="command") + for feature in self.app.features: + if isinstance(feature, AppCommandFeatureProvider): + info = feature.get_command_info() + command_subparser = subparsers.add_parser(info[0], help=info[1]) + feature.setup_arg_parser(command_subparser) + self._map[info[0]] = feature + self._arg_parser = arg_parser + + def setup(self): + self._setup_arg_parser() + + @property + def arg_parser(self) -> argparse.ArgumentParser: + return self._arg_parser + + @property + def map(self) -> dict[str, AppCommandFeatureProvider]: + return self._map + + def run_command(self, _args: Sequence[str] | None = None) -> None: + args = self.arg_parser.parse_args(_args) + self.map[args.command].run_command(args) + + class AppBase: _instance: AppBase | None = None |