diff options
Diffstat (limited to 'tools/cru-py/cru')
-rw-r--r-- | tools/cru-py/cru/_iter.py | 4 | ||||
-rw-r--r-- | tools/cru-py/cru/app.py | 4 | ||||
-rw-r--r-- | tools/cru-py/cru/service/_base.py | 58 | ||||
-rw-r--r-- | tools/cru-py/cru/service/_template.py | 29 | ||||
-rw-r--r-- | tools/cru-py/cru/template.py | 4 |
5 files changed, 82 insertions, 17 deletions
diff --git a/tools/cru-py/cru/_iter.py b/tools/cru-py/cru/_iter.py index 12d1d1f..5d3766a 100644 --- a/tools/cru-py/cru/_iter.py +++ b/tools/cru-py/cru/_iter.py @@ -415,8 +415,8 @@ class CruIterator(Generic[_T]): return self.first_n(1).single_or(fallback) @_wrap - def flatten(self) -> Iterable[_T | Iterable[_T]]: - return _Generic.iterable_flatten(self) + def flatten(self, max_depth: int = -1) -> Iterable[Any]: + return _Generic.iterable_flatten(self, max_depth) def select_by_indices(self, indices: Iterable[int]) -> CruIterator[_T]: index_set = set(indices) diff --git a/tools/cru-py/cru/app.py b/tools/cru-py/cru/app.py index c9e57f4..d45fd30 100644 --- a/tools/cru-py/cru/app.py +++ b/tools/cru-py/cru/app.py @@ -40,6 +40,10 @@ class ApplicationPath: return self._full_path @property + def full_path_str(self) -> str: + return str(self._full_path) + + @property def is_dir(self) -> bool: return self._is_dir diff --git a/tools/cru-py/cru/service/_base.py b/tools/cru-py/cru/service/_base.py index 707fb66..7bb09ad 100644 --- a/tools/cru-py/cru/service/_base.py +++ b/tools/cru-py/cru/service/_base.py @@ -1,23 +1,73 @@ +from __future__ import annotations + from argparse import ArgumentParser, Namespace -from typing import Protocol +from abc import ABC, abstractmethod +from collections.abc import Iterable + +from cru import CruIterator, CruInternalError from cru.app import ApplicationPath, CruApplication -class AppFunction(Protocol): +class AppFeatureProvider(ABC): + def __init__(self, name: str, /, app: AppBase | None = None): + super().__init__() + self._name = name + self._app = app if app else AppBase.get_instance() + self._app_paths: list[ApplicationPath] = [] + self.app.add_app_feature(self) + + @property + def app(self) -> AppBase: + return self._app + + @property + def name(self) -> str: + return self._name + @property - def name(self) -> str: ... + def app_paths(self) -> list[ApplicationPath]: + return self._app_paths + + def add_app_path(self, subpath: str, is_dir: bool) -> ApplicationPath: + p = ApplicationPath(self.app.app_dir, subpath, is_dir) + self._app_paths.append(p) + return p + @abstractmethod def add_arg_parser(self, arg_parser: ArgumentParser) -> None: ... + @abstractmethod def run_command(self, args: Namespace) -> None: ... class AppBase(CruApplication): + _instance: AppBase | None = None + + @staticmethod + def get_instance() -> AppBase: + if AppBase._instance is None: + raise CruInternalError("App instance not initialized") + return AppBase._instance + def __init__(self, name: str, app_dir: str): super().__init__(name) + AppBase._instance = self self._app_dir = app_dir - self._template_dir = ApplicationPath(app_dir, "templates", True) + self._app_features: list[AppFeatureProvider] = [] @property def app_dir(self) -> str: return self._app_dir + + @property + def app_features(self) -> list[AppFeatureProvider]: + return self._app_features + + @property + def app_paths(self) -> Iterable[ApplicationPath]: + return ( + CruIterator(self._app_features).transform(lambda x: x.app_paths).flatten(1) + ) + + def add_app_feature(self, feature: AppFeatureProvider) -> None: + self._app_features.append(feature) diff --git a/tools/cru-py/cru/service/_template.py b/tools/cru-py/cru/service/_template.py index 0ca4b63..5da00ba 100644 --- a/tools/cru-py/cru/service/_template.py +++ b/tools/cru-py/cru/service/_template.py @@ -1,20 +1,31 @@ from argparse import ArgumentParser, Namespace -from ._base import AppBase, AppFunction +from ._base import AppFeatureProvider +from cru.app import ApplicationPath +from cru.template import TemplateTree -class TemplateManager(AppFunction): - def __init__(self, app: AppBase): - self._app = app - pass + +class TemplateManager(AppFeatureProvider): + def __init__(self, prefix: str = "CRUPEST"): + super().__init__("template-manager") + self._templates_dir = self.add_app_path("templates", True) + self._generated_dir = self.add_app_path("generated", True) + self._template_tree = TemplateTree( + prefix, self._templates_dir.full_path_str, self._generated_dir.full_path_str + ) + + @property + def templates_dir(self) -> ApplicationPath: + return self._templates_dir @property - def name(self): - return "template-manager" + def generated_dir(self) -> ApplicationPath: + return self._generated_dir def add_arg_parser(self, arg_parser: ArgumentParser) -> None: subparsers = arg_parser.add_subparsers(dest="template_command") - list_parser = subparsers.add_parser("list", help="List templates") - generate_parser = subparsers.add_parser("generate", help="Generate template") + list_parser = subparsers.add_parser("list", help="List templates.") + generate_parser = subparsers.add_parser("generate", help="Generate template.") def run_command(self, args: Namespace) -> None: ... diff --git a/tools/cru-py/cru/template.py b/tools/cru-py/cru/template.py index 2161804..ccb3ad8 100644 --- a/tools/cru-py/cru/template.py +++ b/tools/cru-py/cru/template.py @@ -79,14 +79,14 @@ class TemplateTree: prefix: str, source: str, destination: str, - exclude: Iterable[str], + exclude: Iterable[str] | None = None, template_file_suffix: str = ".template", ): self._prefix = prefix self._files: list[CruTemplateFile] | None = None self._source = source self._destination = destination - self._exclude = [os.path.normpath(p) for p in exclude] + self._exclude = [os.path.normpath(p) for p in exclude or []] self._template_file_suffix = template_file_suffix @property |