Source code for simplebench.reporters.choices.choices

"""Choices for reporters."""
# pylint: disable=useless-parent-delegation
from __future__ import annotations

from typing import TYPE_CHECKING, Iterable

from simplebench.exceptions import SimpleBenchTypeError
from simplebench.reporters.choices._base import _BaseChoices
from simplebench.reporters.choices.exceptions import _ChoicesErrorTag

_CHOICE_IMPORTED: bool = False
"""Indicates whether :class:`~simplebench.reporters.choice.Choice` has been imported yet."""


[docs] def deferred_choice_import() -> None: """Deferred import of :class:`~simplebench.reporters.choice.Choice` to avoid circular imports during initialization.""" global Choice, _CHOICE_IMPORTED # pylint: disable=global-statement if _CHOICE_IMPORTED: return from simplebench.reporters.choice.choice import Choice # pylint: disable=import-outside-toplevel _CHOICE_IMPORTED = True
if TYPE_CHECKING: from simplebench.reporters.choice.choice import Choice
[docs] class Choices(_BaseChoices['Choice', _ChoicesErrorTag]): """A dictionary-like container for :class:`~simplebench.reporters.choice.Choice` instances. This class enforces that only :class:`~simplebench.reporters.choice.Choice` instances can be added to it, and provides methods to manage and retrieve those instances. It is designed to be used in the context of reporters that require a collection of :class:`~simplebench.reporters.choice.Choice` instances. """ def __init__(self, choices: Iterable[Choice] | Choices | None = None) -> None: """Construct a :class:`~.Choices` container. :param choices: An ``Iterable`` of :class:`~simplebench.reporters.choice.Choice` instances or another :class:`~.Choices` instance to initialize the container with. If ``None``, an empty container is created. :type choices: Iterable[:class:`~simplebench.reporters.choice.Choice`] | \ :class:`~.Choices` | None """ deferred_choice_import() super().__init__(item_type=Choice, error_tag_enum=_ChoicesErrorTag, choices=choices)
[docs] def add(self, choice: Choice) -> None: """Add a :class:`~simplebench.reporters.choice.Choice` instance to the container. The ``choice.name`` attribute is used as the key in the container and is required to be unique withing the container. :param choice: The :class:`~simplebench.reporters.choice.Choice` instance to add. :type choice: :class:`~simplebench.reporters.choice.Choice` :raises SimpleBenchTypeError: If the argument is not a :class:`~simplebench.reporters.choice.Choice` instance. :raises SimpleBenchValueError: If a :class:`~simplebench.reporters.choice.Choice` with the same name already exists in the container. """ super().add(choice)
[docs] def all_choice_args(self) -> set[str]: """Return a set of all ``Namespace`` arg names from all :class:`~simplebench.reporters.choice.Choice` instances in the container. :return: A set of all ``Namespace`` arg names from all :class:`~simplebench.reporters.choice.Choice` instances. :rtype: set[str] """ return set(self._args_index.keys())
[docs] def all_choice_flags(self) -> set[str]: """Return a set of all CLI flags from all :class:`~simplebench.reporters.choice.Choice` instances in the container. :return: A set of all CLI flags from all :class:`~simplebench.reporters.choice.Choice` instances. :rtype: set[str] """ return set(self._flags_index.keys())
[docs] def get_choice_for_arg(self, arg: str) -> Choice | None: """Return the :class:`~simplebench.reporters.choice.Choice` instance associated with the given ``Namespace`` arg name. :param arg: The ``Namespace`` arg name to look up. :type arg: str :return: The :class:`~simplebench.reporters.choice.Choice` instance associated with the arg, or ``None`` if no such :class:`~simplebench.reporters.choice.Choice` exists. :rtype: :class:`~simplebench.reporters.choice.Choice` | None :raises SimpleBenchTypeError: If the arg is not a string. """ if not isinstance(arg, str): raise SimpleBenchTypeError( "arg must be a string", tag=_ChoicesErrorTag.GET_CHOICE_FOR_ARG_INVALID_ARG_TYPE) return self._args_index.get(arg, None)
[docs] def extend( # type: ignore[reportIncompatibleMethodOverride, override] self, choices: Iterable[Choice] | Choices) -> None: """Add :class:`~simplebench.reporters.choice.Choice` instances to the container. It does so by adding each :class:`~simplebench.reporters.choice.Choice` in the provided ``Iterable`` of :class:`~simplebench.reporters.choice.Choice` or by adding the :class:`~simplebench.reporters.choice.Choice` instances from the provided :class:`~.Choices` instance. :param choices: An ``Iterable`` of :class:`~simplebench.reporters.choice.Choice` instances or an instance of :class:`~.Choices`. :type choices: Iterable[:class:`~simplebench.reporters.choice.Choice`] | \ :class:`~.Choices` :raises SimpleBenchTypeError: If the ``choices`` argument is not an ``Iterable`` of :class:`~simplebench.reporters.choice.Choice` instances or a :class:`~.Choices` instance. :raises SimpleBenchValueError: If any :class:`~simplebench.reporters.choice.Choice` in the ``Iterable`` has a duplicate name that already exists in the container. """ super().extend(choices)
[docs] def remove(self, name: str) -> None: """Remove a :class:`~simplebench.reporters.choice.Choice` instance from the container by its name. :param name: The name of the :class:`~simplebench.reporters.choice.Choice` instance to remove. :type name: str :raises SimpleBenchKeyError: If no :class:`~simplebench.reporters.choice.Choice` under the given name exists in the container. """ super().remove(name)
# custom __delitem__ method to maintain indexes def __delitem__(self, key: str) -> None: """Remove a :class:`~simplebench.reporters.choice.Choice` instance from the container by its name. :param name: The name of the :class:`~simplebench.reporters.choice.Choice` instance to remove. :type name: str :raises SimpleBenchKeyError: If no :class:`~simplebench.reporters.choice.Choice` under the given name exists in the container. """ super().__delitem__(key) # custom __setitem__ method to make Choices into a type restricted dict # We override __setitem__ to enforce that only Choice instances # can be added to the container, and to maintain internal indexes. def __setitem__(self, key: str, value: Choice) -> None: """Set a value in the :class:`~.Choices` container. This restricts setting values to only :class:`~simplebench.reporters.choice.Choice` instances with string keys and raises an error otherwise. It also prevents duplicate :class:`~simplebench.reporters.choice.Choice` names. It also restricts the key to match the ``Choice.name`` attribute and updates the internal indexes accordingly. .. code-block:: python choices = Choices() choice = Choice(...) choices[choice.name] = choice :param key: The key under which to store the :class:`~simplebench.reporters.choice.Choice` instance. :type key: str :param value: The :class:`~simplebench.reporters.choice.Choice` instance to add. :type value: :class:`~simplebench.reporters.choice.Choice` :raises SimpleBenchTypeError: If the key is not a string or the value is not a :class:`~simplebench.reporters.choice.Choice` instance. :raises SimpleBenchValueError: If a :class:`~simplebench.reporters.choice.Choice` with the same name already exists in the container; if the key does not match the ``Choice.name`` attribute; or if a :class:`~simplebench.reporters.choice.Choice` with the same flag already exists in the container. """ super().__setitem__(key, value)