aboutsummaryrefslogtreecommitdiff
path: root/tools/cru-py/cru
diff options
context:
space:
mode:
Diffstat (limited to 'tools/cru-py/cru')
-rw-r--r--tools/cru-py/cru/_iter.py4
-rw-r--r--tools/cru-py/cru/app.py4
-rw-r--r--tools/cru-py/cru/service/_base.py58
-rw-r--r--tools/cru-py/cru/service/_template.py29
-rw-r--r--tools/cru-py/cru/template.py4
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