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

25 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""" 

5Toolchain Click group and shared decorator definitions. 

6 

7This module is separated from ``__init__.py`` to avoid circular imports: 

8subcommand modules import the ``toolchain`` group and ``common_options`` 

9from here, while ``__init__.py`` imports subcommand modules to trigger 

10their registration. 

11""" 

12 

13from __future__ import annotations 

14 

15import functools 

16from typing import Any 

17 

18import click 

19 

20from mafw.devtools.toolchain.default_registry import get_default_registry 

21from mafw.tools.click_extensions import AbbreviateGroup 

22 

23CONTEXT_SETTINGS = {'help_option_names': ['-h', '--help']} 

24"""Click context settings for command line help aliases.""" 

25 

26 

27@click.group( 

28 cls=AbbreviateGroup, 

29 context_settings=CONTEXT_SETTINGS, 

30 help='Toolchain management commands.', 

31) 

32@click.option( 

33 '--include-host', 

34 is_flag=True, 

35 default=False, 

36 help='Include host-category tools (pipx-managed) in subcommand processing.', 

37) 

38@click.option( 

39 '--exclude-host', 

40 is_flag=True, 

41 default=False, 

42 help='Exclude host-category tools from subcommand processing (default behaviour).', 

43) 

44@click.pass_context 

45def toolchain(ctx: click.Context, include_host: bool, exclude_host: bool) -> None: 

46 """Manage development toolchain tools.""" 

47 if include_host and exclude_host: 

48 raise click.UsageError('--include-host and --exclude-host are mutually exclusive.') 

49 ctx.ensure_object(dict) 

50 # Default behaviour (neither flag) is to exclude host tools. 

51 ctx.obj['include_host'] = include_host 

52 ctx.obj['registry'] = get_default_registry() 

53 

54 

55def common_options(fn: Any) -> Any: 

56 """Shared decorator applying ``-i``/``--include`` and ``-e``/``--exclude`` options. 

57 

58 These repeatable options allow subcommands to filter which tools are 

59 processed by name. They are mutually exclusive: specifying both in the 

60 same invocation triggers a :class:`~click.UsageError` at filtering time 

61 (enforced by :func:`~mafw.devtools.toolchain.filtering.resolve_tools`). 

62 

63 The decorated function receives ``include`` and ``exclude`` keyword 

64 arguments as tuples of tool-name strings. 

65 """ 

66 

67 @click.option( 

68 '-i', 

69 '--include', 

70 multiple=True, 

71 type=click.STRING, 

72 help='Process only the named tool(s). Repeatable.', 

73 ) 

74 @click.option( 

75 '-e', 

76 '--exclude', 

77 multiple=True, 

78 type=click.STRING, 

79 help='Skip the named tool(s). Repeatable.', 

80 ) 

81 @functools.wraps(fn) 

82 def wrapper(*args: Any, **kwargs: Any) -> Any: 

83 return fn(*args, **kwargs) 

84 

85 return wrapper