Source code for concrete_settings.behaviors.behavior

import types
from typing import Any, Union

from ..settings import Settings
from .. import Setting, PropertySetting


class GenericBehaviorMeta(type):
    def __call__(cls, *args, init_with_arguments=False, **kwargs):
        # Explicitly tell the metaclass that
        # Behavior.__init__(arg1, arg2, ...)
        # is expected
        # Case: @validate(validator1, ...)

        if init_with_arguments:
            return super().__call__(*args, **kwargs)

        # Act as a decorator
        _decorating_setting_or_method = (
            len(args) == 1
            and len(kwargs) == 0
            and isinstance(args[0], (Setting, types.FunctionType))
        )

        if _decorating_setting_or_method:
            if isinstance(args[0], types.FunctionType):
                setting = PropertySetting(args[0])
            else:
                setting = args[0]

            bhv = super().__call__()
            return bhv(setting)
        else:
            bhv = super().__call__(*args, **kwargs)
            return bhv

    def __rmatmul__(cls, setting: Any):
        if not isinstance(setting, Setting):
            setting = Setting(setting)

        bhv = cls()
        return bhv(setting)


class BehaviorWithArgumentsMeta(GenericBehaviorMeta):
    def __call__(cls, *args, **kwargs):
        return super().__call__(*args, **kwargs, init_with_arguments=True)


[docs]class Behavior(metaclass=GenericBehaviorMeta): def __call__(self, setting_or_method: Union[Setting, types.FunctionType]): setting: Setting if isinstance(setting_or_method, types.FunctionType): setting = PropertySetting(setting_or_method) else: setting = setting_or_method self.attach(setting) return setting def __rmatmul__(self, setting: Any): if not isinstance(setting, Setting): setting = Setting(setting) self.decorate(setting) return setting def attach(self, setting: Setting): setting._behaviors.append(self)
[docs] def decorate(self, setting: Setting): pass
[docs]class GetterSetterBehavior(Behavior): def decorate(self, setting: Setting): # replace setting.get_value and .set_value by # corresponding behavior methods self._setting_get_value = setting.get_value self._setting_set_value = setting.set_value setting.get_value = types.MethodType(self.get_value, setting) # type: ignore setting.set_value = types.MethodType(self.set_value, setting) # type: ignore super().decorate(setting)
[docs] def get_value(self, setting: Setting, owner: Settings) -> Any: return self._setting_get_value(owner)
[docs] def set_value(self, setting: Setting, owner: Settings, value): self._setting_set_value(owner, value)