diff --git a/src/ahriman/application/handlers/handler.py b/src/ahriman/application/handlers/handler.py index 6886b08f..23a582ba 100644 --- a/src/ahriman/application/handlers/handler.py +++ b/src/ahriman/application/handlers/handler.py @@ -23,7 +23,7 @@ import argparse import logging from multiprocessing import Pool -from typing import List, Type +from typing import Set, Type from ahriman.application.lock import Lock from ahriman.core.configuration import Configuration @@ -63,11 +63,11 @@ class Handler: architectures = cls.extract_architectures(args) with Pool(len(architectures)) as pool: result = pool.starmap( - cls._call, [(args, architecture) for architecture in set(architectures)]) + cls._call, [(args, architecture) for architecture in architectures]) return 0 if all(result) else 1 @classmethod - def extract_architectures(cls: Type[Handler], args: argparse.Namespace) -> List[str]: + def extract_architectures(cls: Type[Handler], args: argparse.Namespace) -> Set[str]: """ get known architectures :param args: command line args @@ -76,13 +76,16 @@ class Handler: if args.architecture is None: raise MissingArchitecture(args.command) if args.architecture: - architectures: List[str] = args.architecture # avoid mypy warning - return architectures + return set(args.architecture) config = Configuration() config.load(args.configuration) root = config.getpath("repository", "root") - return RepositoryPaths.known_architectures(root) + architectures = RepositoryPaths.known_architectures(root) + + if not architectures: + raise MissingArchitecture(args.command) + return architectures @classmethod def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration) -> None: diff --git a/src/ahriman/models/repository_paths.py b/src/ahriman/models/repository_paths.py index 9eaa398a..12c6ebfa 100644 --- a/src/ahriman/models/repository_paths.py +++ b/src/ahriman/models/repository_paths.py @@ -21,7 +21,7 @@ from __future__ import annotations from dataclasses import dataclass from pathlib import Path -from typing import List, Type +from typing import Set, Type @dataclass @@ -79,18 +79,18 @@ class RepositoryPaths: return self.root / "sources" / self.architecture @classmethod - def known_architectures(cls: Type[RepositoryPaths], root: Path) -> List[str]: + def known_architectures(cls: Type[RepositoryPaths], root: Path) -> Set[str]: """ get known architectures :param root: repository root :return: list of architectures for which tree is created """ paths = cls(root, "") - return [ + return { path.name for path in paths.repository.iterdir() if path.is_dir() - ] + } def create_tree(self) -> None: """ diff --git a/tests/ahriman/application/handlers/test_handler.py b/tests/ahriman/application/handlers/test_handler.py index 78d91d25..cd7c9efa 100644 --- a/tests/ahriman/application/handlers/test_handler.py +++ b/tests/ahriman/application/handlers/test_handler.py @@ -57,12 +57,18 @@ def test_extract_architectures(args: argparse.Namespace, mocker: MockerFixture) known_architectures_mock.assert_called_once() -def test_extract_architectures_specified(args: argparse.Namespace) -> None: +def test_extract_architectures_empty(args: argparse.Namespace, mocker: MockerFixture) -> None: """ - must return architecture list if it has been specified + must raise exception if no available architectures found """ - architectures = args.architecture = ["i686", "x86_64"] - assert Handler.extract_architectures(args) == architectures + args.architecture = [] + args.command = "config" + args.configuration = Path("") + mocker.patch("ahriman.core.configuration.Configuration.getpath") + mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures", return_value=set()) + + with pytest.raises(MissingArchitecture): + Handler.extract_architectures(args) def test_extract_architectures_exception(args: argparse.Namespace) -> None: @@ -75,6 +81,14 @@ def test_extract_architectures_exception(args: argparse.Namespace) -> None: Handler.extract_architectures(args) +def test_extract_architectures_specified(args: argparse.Namespace) -> None: + """ + must return architecture list if it has been specified + """ + architectures = args.architecture = ["i686", "x86_64"] + assert Handler.extract_architectures(args) == set(architectures) + + def test_run(args: argparse.Namespace, configuration: Configuration) -> None: """ must raise NotImplemented for missing method