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
« 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.
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"""
13from __future__ import annotations
15import functools
16from typing import Any
18import click
20from mafw.devtools.toolchain.default_registry import get_default_registry
21from mafw.tools.click_extensions import AbbreviateGroup
23CONTEXT_SETTINGS = {'help_option_names': ['-h', '--help']}
24"""Click context settings for command line help aliases."""
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()
55def common_options(fn: Any) -> Any:
56 """Shared decorator applying ``-i``/``--include`` and ``-e``/``--exclude`` options.
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`).
63 The decorated function receives ``include`` and ``exclude`` keyword
64 arguments as tuples of tool-name strings.
65 """
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)
85 return wrapper