Source code for mafw.devtools.toolchain.filtering

#  Copyright 2026 European Union
#  Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
#  SPDX-License-Identifier: EUPL-1.2
"""
Tool filtering utility for the toolchain command group.

This module provides :func:`resolve_tools`, a shared function used by all CLI
subcommands to determine which tools to process based on the ``--include-host``,
``-i``/``--include``, and ``-e``/``--exclude`` options. It enforces mutual
exclusivity between include and exclude filters, warns on unrecognized tool
names, and preserves the original registration order from the registry.
"""

from __future__ import annotations

import warnings

from mafw.devtools import DevtoolsError
from mafw.devtools.toolchain.base import ToolChainTool
from mafw.devtools.toolchain.registry import ToolRegistry


[docs] def resolve_tools( registry: ToolRegistry, *, include: tuple[str, ...] = (), exclude: tuple[str, ...] = (), include_host: bool = False, ) -> list[ToolChainTool]: """Filter the registry based on CLI options. The filtering pipeline proceeds in order: 1. Reject mutually exclusive ``include`` and ``exclude`` arguments. 2. Start with all tools from the registry (preserving insertion order). 3. If *include_host* is ``False``, remove tools with category ``"host"``. 4. If *include* is non-empty, keep only tools whose name is in the set (emit a warning for each unrecognized name). 5. If *exclude* is non-empty, remove tools whose name is in the set (emit a warning for each unrecognized name). :param registry: The central tool registry to query. :param include: Tool names to include exclusively. Only tools whose ``name`` matches one of these values will be returned. :param exclude: Tool names to exclude. Tools whose ``name`` matches one of these values will be removed from the result. :param include_host: When ``False`` (the default), tools with ``category="host"`` are excluded before any name-based filtering. :return: A list of tools in their original registration order. :raises DevtoolsError: If both *include* and *exclude* are non-empty (mutual exclusivity violation). """ # Step 1: Enforce mutual exclusivity of include and exclude. if include and exclude: raise DevtoolsError('--include and --exclude are mutually exclusive; specify one or the other, not both.') # Step 2: Start with all registered tools. tools = registry.all() # Step 3: Filter out host tools unless explicitly included. if not include_host: tools = [t for t in tools if t.category != 'host'] # Step 4: Apply include filter (keep only named tools). if include: include_set = set(include) # Gather the set of known tool names from the current (possibly host-filtered) list. known_names = {t.name for t in tools} for name in include_set: if name not in known_names: warnings.warn( f'Unrecognized tool name in --include: {name!r}', stacklevel=2, ) tools = [t for t in tools if t.name in include_set] # Step 5: Apply exclude filter (remove named tools). if exclude: exclude_set = set(exclude) # Gather the set of known tool names from the current (possibly host-filtered) list. known_names = {t.name for t in tools} for name in exclude_set: if name not in known_names: warnings.warn( f'Unrecognized tool name in --exclude: {name!r}', stacklevel=2, ) tools = [t for t in tools if t.name not in exclude_set] return tools