diff options
author | crupest <crupest@outlook.com> | 2024-11-11 01:12:29 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-01-11 17:01:20 +0800 |
commit | b9788b23bbd000d2a2d14402b4e2abacd5a57365 (patch) | |
tree | a5cdbb5fb3ac2ff609efc822e294182dcaa0876d /tools/cru-py/cru/service/_config.py | |
parent | 0d7dd933dfab91faf1a42b7883eb059d7fb31d80 (diff) | |
download | crupest-b9788b23bbd000d2a2d14402b4e2abacd5a57365.tar.gz crupest-b9788b23bbd000d2a2d14402b4e2abacd5a57365.tar.bz2 crupest-b9788b23bbd000d2a2d14402b4e2abacd5a57365.zip |
HALF WORK: 2024.1.11 - 2
Diffstat (limited to 'tools/cru-py/cru/service/_config.py')
-rw-r--r-- | tools/cru-py/cru/service/_config.py | 97 |
1 files changed, 95 insertions, 2 deletions
diff --git a/tools/cru-py/cru/service/_config.py b/tools/cru-py/cru/service/_config.py index 018b45b..6e1edda 100644 --- a/tools/cru-py/cru/service/_config.py +++ b/tools/cru-py/cru/service/_config.py @@ -1,3 +1,4 @@ +from cru import CruException, CruUserFriendlyException from cru.config import Configuration, ConfigItem from cru.value import ( INTEGER_VALUE_TYPE, @@ -7,10 +8,42 @@ from cru.value import ( ) from cru.parsing import SimpleLineConfigParser -from ._base import AppFeaturePath, AppFeatureProvider, OWNER_NAME +from ._base import AppFeaturePath, AppCommandFeatureProvider, OWNER_NAME -class ConfigManager(AppFeatureProvider): +class AppConfigError(CruException): + pass + + +class AppConfigDuplicateItemsError(AppConfigError): + def __init__( + self, message: str, items: list[SimpleLineConfigParser.Item], *args, **kwargs + ) -> None: + super().__init__(message, *args, **kwargs) + self._items = items + + @property + def duplicate_items(self) -> list[SimpleLineConfigParser.Item]: + return self._items + + @staticmethod + def duplicate_items_to_friendly_message( + items: list[SimpleLineConfigParser.Item], + ) -> str: + return "".join( + f"line {item.line_number}: {item.key}={item.value}\n" for item in items + ) + + def to_friendly_error(self) -> CruUserFriendlyException: + e = CruUserFriendlyException( + f"Duplicate configuration items detected:\n" + f"{self.duplicate_items_to_friendly_message(self.duplicate_items)}" + ) + e.__cause__ = self + return e + + +class ConfigManager(AppCommandFeatureProvider): def __init__(self) -> None: super().__init__("config-manager") configuration = Configuration() @@ -99,6 +132,36 @@ class ConfigManager(AppFeatureProvider): def config_map(self) -> dict[str, str]: raise NotImplementedError() + def _parse_config_file(self) -> SimpleLineConfigParser.Result | None: + if not self.config_file_path.check_self(): + return None + parser = SimpleLineConfigParser() + return parser.parse(self.config_file_path.full_path.read_text()) + + def _check_duplicate( + self, + result: SimpleLineConfigParser.Result + | dict[str, list[SimpleLineConfigParser.Item]], + ) -> dict[str, str]: + if isinstance(result, SimpleLineConfigParser.Result): + result = result.cru_iter().group_by(lambda i: i.key) + + config = {} + error_items = [] + for key, items in result.items(): + config[key] = items[0].value + for item in items[1:]: + error_items.append(item) + + if len(error_items) > 0: + raise AppConfigDuplicateItemsError("Duplicate items found.", error_items) + + return config + + def _check_config_file(self) -> dict[str, str]: + # TODO: Continue here! + raise NotImplementedError() + def reload_config_file(self) -> bool: self.configuration.reset_all() if not self.config_file_path.check_self(): @@ -107,3 +170,33 @@ class ConfigManager(AppFeatureProvider): parse_result = parser.parse(self.config_file_path.full_path.read_text()) config_dict = parse_result.cru_iter().group_by(lambda i: i.key) return True + + def print_app_config_info(self): + for item in self.configuration: + print(f"{item.name} ({item.value_type.name}): {item.description}") + + def get_command_info(self): + return "config", "Manage configuration." + + def setup_arg_parser(self, arg_parser) -> None: + subparsers = arg_parser.add_subparsers(dest="config_command") + _print_app_parser = subparsers.add_parser( + "print-app", + help="Print application configuration information " + "of the items defined in the application.", + ) + _check_config_parser = subparsers.add_parser( + "check", + help="Check the validity of the configuration file.", + ) + _check_config_parser.add_argument( + "-f", + "--format-only", + action="store_true", + help="Only check content format, not " + "for application configuration requirements.", + ) + + def run_command(self, args) -> None: + if args.config_command == "print-app": + self.print_app_config_info() |