# Copyright 2026 European Union
# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
# SPDX-License-Identifier: EUPL-1.2
"""
Toolchain Click group and shared decorator definitions.
This module is separated from ``__init__.py`` to avoid circular imports:
subcommand modules import the ``toolchain`` group and ``common_options``
from here, while ``__init__.py`` imports subcommand modules to trigger
their registration.
"""
from __future__ import annotations
import functools
from typing import Any
import click
from mafw.devtools.toolchain.default_registry import get_default_registry
from mafw.tools.click_extensions import AbbreviateGroup
CONTEXT_SETTINGS = {'help_option_names': ['-h', '--help']}
"""Click context settings for command line help aliases."""
@click.group(
cls=AbbreviateGroup,
context_settings=CONTEXT_SETTINGS,
help='Toolchain management commands.',
)
@click.option(
'--include-host',
is_flag=True,
default=False,
help='Include host-category tools (pipx-managed) in subcommand processing.',
)
@click.option(
'--exclude-host',
is_flag=True,
default=False,
help='Exclude host-category tools from subcommand processing (default behaviour).',
)
@click.pass_context
def toolchain(ctx: click.Context, include_host: bool, exclude_host: bool) -> None:
"""Manage development toolchain tools."""
if include_host and exclude_host:
raise click.UsageError('--include-host and --exclude-host are mutually exclusive.')
ctx.ensure_object(dict)
# Default behaviour (neither flag) is to exclude host tools.
ctx.obj['include_host'] = include_host
ctx.obj['registry'] = get_default_registry()
[docs]
def common_options(fn: Any) -> Any:
"""Shared decorator applying ``-i``/``--include`` and ``-e``/``--exclude`` options.
These repeatable options allow subcommands to filter which tools are
processed by name. They are mutually exclusive: specifying both in the
same invocation triggers a :class:`~click.UsageError` at filtering time
(enforced by :func:`~mafw.devtools.toolchain.filtering.resolve_tools`).
The decorated function receives ``include`` and ``exclude`` keyword
arguments as tuples of tool-name strings.
"""
@click.option(
'-i',
'--include',
multiple=True,
type=click.STRING,
help='Process only the named tool(s). Repeatable.',
)
@click.option(
'-e',
'--exclude',
multiple=True,
type=click.STRING,
help='Skip the named tool(s). Repeatable.',
)
@functools.wraps(fn)
def wrapper(*args: Any, **kwargs: Any) -> Any:
return fn(*args, **kwargs)
return wrapper