Source code for giant.utilities.mixin_classes.user_option_configured

"""
This module provides the :class:`UserOptionConfigured` mixin class that enables classes to be
configured using :class:`.UserOptions`-derived classes while maintaining the ability to reset
to the original configuration state.

The mixin pattern allows for clean separation of configuration logic and provides a consistent
interface for option management across different classes.

Example:
    Basic usage of the UserOptionConfigured mixin::

        from giant.utilities.options import UserOptions
        from giant.utilities.mixin_classes.user_option_configured import UserOptionConfigured
        from dataclasses import dataclass

        @dataclass
        class MyOptions(UserOptions):
            a: int = 5
            b: float = -32.1

        class MyUsefulClass(UserOptionConfigured[MyOptions], MyOptions):
            def __init__(self, options: MyOptions = None):
                super().__init__(MyOptions, options)

        # Usage
        my_useful_inst = MyUsefulClass()
        my_useful_inst.a = 6  # Make a change
        print(my_useful_inst.a)  # Output: 6
        my_useful_inst.reset_settings()  # Reset to original
        print(my_useful_inst.a)  # Output: 5

.. Note::
    The :class:`UserOptionConfigured` class should come first in the inheritance order
    due to Method Resolution Order (MRO) requirements.

"""

from typing import Generic, TypeVar

from giant.utilities.options import UserOptions


OptionsT = TypeVar("OptionsT", bound=UserOptions)
"""
Type variable bound to UserOptions for type safety
"""


[docs] class UserOptionConfigured(Generic[OptionsT]): """ Mixin class providing UserOptions-based configuration with reset capability. This mixin class enables classes to be configured using :class:`UserOptions`-derived classes and provides the ability to reset the class to its default (initially provided) state. The class works in conjunction with the :class:`UserOptions` ABC to provide: * Automatic configuration of class instances based on provided options * Storage of original configuration for reset functionality * Type-safe option handling through generic typing To use this mixin, subclass it with the :class:`UserOptions` subclass as the type parameter:: class MyUsefulClass(UserOptionConfigured[MyOptions], MyOptions): def __init__(self, options: MyOptions = None): super().__init__(MyOptions, options) :param OptionsT: The :class:`UserOptions`-derived class type for configuration :attr original_options: The original configuration used during initialization. This is stored as a deep copy and used for reset operations. .. Warning:: If options are not provided during initialization, default initialization of the options_type class will be used. """ def __init__(self, options_type: type[OptionsT], *args, options: OptionsT | None = None, **kwargs) -> None: """ :param options_type: The type of the :class:`.UserOptions` to use :param options: An optional oinstance of `options_type` preconfigured. """ super().__init__(*args, **kwargs) if options is None: options = options_type() options.apply_options(self) self._original_options: OptionsT = options """ The original configuration for this class """
[docs] def reset_settings(self) -> None: """ Resets the class to the state it was originally initialized with. """ self.original_options.apply_options(self)
@property def original_options(self) -> OptionsT: """ Get the original configuration options. :returns: OptionsT: The original options used during initialization. .. Warning:: Modifying the returned object will affect reset behavior. """ return self._original_options @original_options.setter def original_options(self, value: OptionsT) -> None: """ Manually Set the original configuration options. :param value: The options to store as original configuration. .. note:: Generally this shouldn't be used. If you want to manually change options you can do so directly just by using `my_options.apply_options(my_class_inst)` """ self._original_options = value