Coverage for src/mafw/devtools/cli/toolchain/verify_cmd.py: 100%

36 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-26 09:13 +0000

1# Copyright 2026 European Union 

2# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu) 

3# SPDX-License-Identifier: EUPL-1.2 

4""" 

5Verify subcommand for the toolchain command group. 

6 

7This module implements the ``devtools toolchain verify`` command, which 

8iterates over all applicable tools with a Rich progress spinner, calls each 

9tool's :meth:`~mafw.devtools.toolchain.base.ToolChainTool.verify` method, and 

10reports any configuration inconsistencies found. Exceptions during verification 

11are treated as implicit issues. The exit code reflects whether any issues were 

12detected (exit 1) or all tools are consistent (exit 0). 

13""" 

14 

15from __future__ import annotations 

16 

17import sys 

18 

19import click 

20from rich.console import Console 

21from rich.progress import MofNCompleteColumn, Progress, SpinnerColumn, TextColumn 

22 

23from mafw.devtools.cli.toolchain._group import common_options, toolchain 

24from mafw.devtools.toolchain.base import Issue 

25from mafw.devtools.toolchain.filtering import resolve_tools 

26 

27 

28@toolchain.command(name='verify') 

29@common_options 

30@click.pass_context 

31def verify(ctx: click.Context, include: tuple[str, ...], exclude: tuple[str, ...]) -> None: 

32 """Verify configuration consistency of all applicable tools. 

33 

34 Iterates over the filtered tool set with a progress spinner, calling each 

35 tool's ``verify()`` method. Issues are printed prefixed with the tool name. 

36 Exceptions during verification are reported as errors and count towards a 

37 non-zero exit code. 

38 """ 

39 registry = ctx.obj['registry'] 

40 include_host: bool = ctx.obj['include_host'] 

41 console = Console() 

42 

43 tools = resolve_tools(registry, include=include, exclude=exclude, include_host=include_host) 

44 

45 # Collect all issues across tools. 

46 all_issues: list[Issue] = [] 

47 had_exception = False 

48 

49 # Iterate tools with a Rich progress spinner for visual feedback. 

50 with Progress( 

51 SpinnerColumn(), 

52 TextColumn('[progress.description]{task.description}'), 

53 MofNCompleteColumn(), 

54 console=console, 

55 transient=True, 

56 ) as progress: 

57 task = progress.add_task('Verifying tools', total=len(tools)) 

58 

59 for idx, tool in enumerate(tools, start=1): 

60 progress.update(task, description=f'Processing tool {idx}/{len(tools)}: {tool.name}') 

61 

62 try: 

63 issues = tool.verify() 

64 except Exception as exc: # noqa: BLE001 

65 # Treat exceptions during verify() as implicit issues. 

66 had_exception = True 

67 console.print( 

68 f'[bold red]{tool.name}[/bold red]: error during verification — {exc}', 

69 style='red', 

70 ) 

71 progress.advance(task) 

72 continue 

73 

74 # Accumulate issues and print each one. 

75 for issue in issues: 

76 all_issues.append(issue) 

77 console.print(f'[bold]{issue.tool_name}[/bold]: {issue.description}') 

78 

79 progress.advance(task) 

80 

81 # Determine exit code and print summary. 

82 if all_issues or had_exception: 

83 sys.exit(1) 

84 else: 

85 console.print('[bold green]All tools verified — no configuration issues found.[/bold green]')