diff --git a/aws_doc_sdk_examples_tools/lliam/domain/commands.py b/aws_doc_sdk_examples_tools/lliam/domain/commands.py index d351c7d..661f8b8 100644 --- a/aws_doc_sdk_examples_tools/lliam/domain/commands.py +++ b/aws_doc_sdk_examples_tools/lliam/domain/commands.py @@ -3,31 +3,34 @@ from typing import List +@dataclass(frozen=True) class Command: - pass + @property + def name(self): + return self.__class__.__name__ -@dataclass +@dataclass(frozen=True) class CreatePrompts(Command): doc_gen_root: str system_prompts: List[str] out_dir: str -@dataclass +@dataclass(frozen=True) class RunAilly(Command): batches: List[str] packages: List[str] -@dataclass +@dataclass(frozen=True) class UpdateReservoir(Command): root: Path batches: List[str] packages: List[str] -@dataclass +@dataclass(frozen=True) class DedupeReservoir(Command): root: Path packages: List[str] diff --git a/aws_doc_sdk_examples_tools/lliam/domain/errors.py b/aws_doc_sdk_examples_tools/lliam/domain/errors.py index 54a0726..3a100d8 100644 --- a/aws_doc_sdk_examples_tools/lliam/domain/errors.py +++ b/aws_doc_sdk_examples_tools/lliam/domain/errors.py @@ -1,12 +1,14 @@ from dataclasses import dataclass -@dataclass +@dataclass(frozen=True) class DomainError: - pass + message: str -@dataclass +@dataclass(frozen=True) class CommandExecutionError(DomainError): command_name: str - message: str + + def __repr__(self): + return f"[{self.command_name}] {self.message}" diff --git a/aws_doc_sdk_examples_tools/lliam/entry_points/lliam_app.py b/aws_doc_sdk_examples_tools/lliam/entry_points/lliam_app.py index bc90464..ba95460 100644 --- a/aws_doc_sdk_examples_tools/lliam/entry_points/lliam_app.py +++ b/aws_doc_sdk_examples_tools/lliam/entry_points/lliam_app.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import List, Optional +from typing import List, Optional, Sequence from typing_extensions import Annotated from datetime import datetime import logging @@ -98,10 +98,10 @@ def dedupe_reservoir( handle_domain_errors(errors) -def handle_domain_errors(errors: List[errors.DomainError]): +def handle_domain_errors(errors: Sequence[errors.DomainError]): if errors: for error in errors: - logger.error(error) + logger.error(error.message) typer.Exit(code=1) diff --git a/aws_doc_sdk_examples_tools/lliam/service_layer/create_prompts.py b/aws_doc_sdk_examples_tools/lliam/service_layer/create_prompts.py index 67f8750..2f3bb3f 100644 --- a/aws_doc_sdk_examples_tools/lliam/service_layer/create_prompts.py +++ b/aws_doc_sdk_examples_tools/lliam/service_layer/create_prompts.py @@ -1,13 +1,15 @@ import logging +from typing import List from aws_doc_sdk_examples_tools.lliam.domain.operations import build_ailly_config from aws_doc_sdk_examples_tools.lliam.domain.commands import CreatePrompts +from aws_doc_sdk_examples_tools.lliam.domain.errors import DomainError from aws_doc_sdk_examples_tools.lliam.service_layer.unit_of_work import FsUnitOfWork logger = logging.getLogger(__name__) -def create_prompts(cmd: CreatePrompts, uow: FsUnitOfWork): +def create_prompts(cmd: CreatePrompts, uow: FsUnitOfWork) -> List[DomainError]: with uow: system_prompts = uow.prompts.get_all(cmd.system_prompts) ailly_config = build_ailly_config(system_prompts) @@ -16,3 +18,5 @@ def create_prompts(cmd: CreatePrompts, uow: FsUnitOfWork): uow.prompts.add(ailly_config) uow.prompts.set_partition(cmd.out_dir) uow.commit() + # TODO: Catch and return any errors + return [] diff --git a/aws_doc_sdk_examples_tools/lliam/service_layer/dedupe_reservoir.py b/aws_doc_sdk_examples_tools/lliam/service_layer/dedupe_reservoir.py index 8a56604..a2a1e42 100644 --- a/aws_doc_sdk_examples_tools/lliam/service_layer/dedupe_reservoir.py +++ b/aws_doc_sdk_examples_tools/lliam/service_layer/dedupe_reservoir.py @@ -4,10 +4,14 @@ from collections import Counter from dataclasses import replace from pathlib import Path -from typing import Dict, Iterable, List +from typing import Dict, List, Sequence from aws_doc_sdk_examples_tools.doc_gen import DocGen from aws_doc_sdk_examples_tools.lliam.domain.commands import DedupeReservoir +from aws_doc_sdk_examples_tools.lliam.domain.errors import ( + DomainError, + CommandExecutionError, +) from aws_doc_sdk_examples_tools.metadata import Example from aws_doc_sdk_examples_tools.yaml_writer import prepare_write, write_many from aws_doc_sdk_examples_tools.project_validator import ValidationConfig @@ -83,7 +87,9 @@ def write_examples(examples: Dict[str, Example], root: Path): write_many(root, writes) -def handle_dedupe_reservoir(cmd: DedupeReservoir, uow: None): +def handle_dedupe_reservoir(cmd: DedupeReservoir, uow: None) -> Sequence[DomainError]: doc_gen = DocGen.from_root(cmd.root, validation=ValidationConfig(check_aws=False)) examples = dedupe_examples(doc_gen.examples, cmd.packages) write_examples(examples, cmd.root) + # TODO: Catch an return any errors + return [] diff --git a/aws_doc_sdk_examples_tools/lliam/service_layer/messagebus.py b/aws_doc_sdk_examples_tools/lliam/service_layer/messagebus.py index 9f551a8..fb8fc08 100644 --- a/aws_doc_sdk_examples_tools/lliam/service_layer/messagebus.py +++ b/aws_doc_sdk_examples_tools/lliam/service_layer/messagebus.py @@ -1,6 +1,6 @@ -from typing import Callable, Dict, Optional, Type +from typing import Any, Callable, Dict, List, Optional, Sequence, Type -from aws_doc_sdk_examples_tools.lliam.domain import commands +from aws_doc_sdk_examples_tools.lliam.domain import commands, errors from aws_doc_sdk_examples_tools.lliam.service_layer import ( create_prompts, dedupe_reservoir, @@ -13,24 +13,35 @@ Message = commands.Command -def handle(message: commands.Command, uow: Optional[unit_of_work.FsUnitOfWork] = None): - queue = [message] +def handle( + message: Any, uow: Optional[unit_of_work.FsUnitOfWork] = None +) -> Sequence[errors.DomainError]: + if isinstance(message, commands.Command): + return handle_command(message, uow) - while queue: - message = queue.pop(0) - if isinstance(message, commands.Command): - return handle_command(message, uow) - else: - raise Exception(f"{message} was not a Command") + return [ + errors.CommandExecutionError( + command_name="Unknown", message=f"{message} was not a Command" + ) + ] -def handle_command(command: commands.Command, uow: Optional[unit_of_work.FsUnitOfWork]): - handler = COMMAND_HANDLERS[type(command)] - errors = handler(command, uow) - return errors +def handle_command( + command: commands.Command, uow: Optional[unit_of_work.FsUnitOfWork] +) -> Sequence[errors.DomainError]: + handler = COMMAND_HANDLERS.get(type(command)) + if not handler: + return [ + errors.CommandExecutionError( + command_name=command.name, message="Handler for not found." + ) + ] + return handler(command, uow) -COMMAND_HANDLERS: Dict[Type[commands.Command], Callable] = { +COMMAND_HANDLERS: Dict[ + Type[commands.Command], Callable[..., Sequence[errors.DomainError]] +] = { commands.CreatePrompts: create_prompts.create_prompts, commands.RunAilly: run_ailly.handle_run_ailly, commands.UpdateReservoir: update_doc_gen.handle_update_reservoir, diff --git a/aws_doc_sdk_examples_tools/lliam/service_layer/run_ailly.py b/aws_doc_sdk_examples_tools/lliam/service_layer/run_ailly.py index fe45a71..ceef3c8 100644 --- a/aws_doc_sdk_examples_tools/lliam/service_layer/run_ailly.py +++ b/aws_doc_sdk_examples_tools/lliam/service_layer/run_ailly.py @@ -2,11 +2,10 @@ import logging import time from collections import defaultdict -from dataclasses import dataclass from datetime import timedelta from pathlib import Path from subprocess import run -from typing import Any, Dict, List, Optional, Set +from typing import Any, Dict, List, Optional, Set, Sequence from aws_doc_sdk_examples_tools.lliam.domain.commands import RunAilly from aws_doc_sdk_examples_tools.lliam.domain.errors import ( @@ -30,7 +29,7 @@ logger = logging.getLogger(__file__) -def handle_run_ailly(cmd: RunAilly, uow: None): +def handle_run_ailly(cmd: RunAilly, uow: None) -> Sequence[DomainError]: resolved_batches = resolve_requested_batches(cmd.batches) errors: List[DomainError] = [] @@ -43,9 +42,7 @@ def handle_run_ailly(cmd: RunAilly, uow: None): run_ailly_single_batch(batch, cmd.packages) except FileNotFoundError as e: errors.append( - CommandExecutionError( - command_name=cmd.__class__.__name__, message=str(e) - ) + CommandExecutionError(message=str(e), command_name=cmd.name) ) total_end_time = time.time() @@ -192,7 +189,7 @@ def parse_ailly_file( return result -def parse_package_name(policy_update: Dict[str, str]) -> Optional[str]: +def parse_package_name(policy_update: Any) -> Optional[str]: if not policy_update: return None diff --git a/aws_doc_sdk_examples_tools/lliam/service_layer/update_doc_gen.py b/aws_doc_sdk_examples_tools/lliam/service_layer/update_doc_gen.py index 442f8d8..340bda0 100644 --- a/aws_doc_sdk_examples_tools/lliam/service_layer/update_doc_gen.py +++ b/aws_doc_sdk_examples_tools/lliam/service_layer/update_doc_gen.py @@ -2,7 +2,7 @@ import json import logging from pathlib import Path -from typing import Dict, Iterable, List +from typing import Dict, Iterable, List, Sequence from aws_doc_sdk_examples_tools.lliam.adapters.repository import DEFAULT_METADATA_PREFIX from aws_doc_sdk_examples_tools.yaml_writer import prepare_write, write_many @@ -12,6 +12,10 @@ BATCH_PREFIX, ) from aws_doc_sdk_examples_tools.lliam.domain.commands import UpdateReservoir +from aws_doc_sdk_examples_tools.lliam.domain.errors import ( + DomainError, + CommandExecutionError, +) from aws_doc_sdk_examples_tools.doc_gen import DocGen, Example logger = logging.getLogger(__name__) @@ -96,7 +100,7 @@ def merge_updates(a: Updates, b: Updates) -> Updates: return merged -def handle_update_reservoir(cmd: UpdateReservoir, uow: None): +def handle_update_reservoir(cmd: UpdateReservoir, uow: None) -> Sequence[DomainError]: update_files = ( [AILLY_DIR_PATH / f"updates_{batch}.json" for batch in cmd.batches] if cmd.batches @@ -105,7 +109,7 @@ def handle_update_reservoir(cmd: UpdateReservoir, uow: None): if not update_files: logger.warning("No IAM update files found to process") - return + return [] doc_gen = DocGen.from_root(cmd.root) @@ -133,3 +137,5 @@ def handle_update_reservoir(cmd: UpdateReservoir, uow: None): updated_examples = update_doc_gen(doc_gen=doc_gen, updates=combined_updates) writes = prepare_write(updated_examples) write_many(cmd.root, writes) + # TODO Catch and return any errors + return []