Source code for concrete_settings.setting

import functools
from typing import Any, Tuple, Optional, Union, Callable, TYPE_CHECKING, List

from .types import GuessSettingType, Undefined
from .validators import Validator

if TYPE_CHECKING:
    from .settings import Settings
    from .behaviors import Behavior


[docs]class Setting: value: Any type_hint: Any validators: Tuple[Validator, ...] name: str override: bool __doc__: str _behaviors: List['Behavior'] def __init__( self, value: Any = Undefined, *, doc: str = '', validators: Tuple[Validator, ...] = (), type_hint: Any = GuessSettingType, override: bool = False, ): self.value = value self.type_hint = type_hint self.validators = tuple(validators) self.__doc__ = doc self.name = "" self.override = override self._behaviors: List['Behavior'] = [] def __set_name__(self, _, name): self.name = name def __get__( self, owner: Optional['Settings'], owner_type=None ) -> Union[Any, 'Setting']: # == class-level access == if not owner: return self # == object-level access == return self.get_value(owner) def get_value(self, owner): return getattr(owner, f"__setting_{self.name}_value", self.value) def __set__(self, owner: 'Settings', val): self.set_value(owner, val) def set_value(self, owner: 'Settings', val): setattr(owner, f"__setting_{self.name}_value", val)
[docs]class PropertySetting(Setting): def __init__(self, *args, **kwargs): decorating_without_arguments = ( len(args) == 1 and len(kwargs) == 0 and callable(args[0]) ) if decorating_without_arguments: self._init_decorator_without_arguments(args[0]) else: if args != (): raise TypeError( 'No positional arguments should be passed to ' f'{self.__class__.__name__}.__init__()' ) if 'value' in kwargs: raise TypeError( '"value" keyword argument should not be passed to ' f'{self.__class__.__name__}.__init__()' ) self._init_decorator_with_arguments(**kwargs) def _init_decorator_without_arguments(self, fget: Callable): super().__init__() self.__call__(fget) def _init_decorator_with_arguments(self, **kwargs): super().__init__(value=Undefined, **kwargs) self.fget = None def __call__(self, fget: Callable): # since functools.update_wrapper overwrite self.__doc__ # we have to temporarily persist it doc_before_wrapping = self.__doc__ functools.update_wrapper(self, fget) # Restore __doc__ self.__doc__ = self.__doc__ or doc_before_wrapping # Extract type_hint from fget annotations if needed if self.type_hint is GuessSettingType: self.type_hint = fget.__annotations__.get('return', self.type_hint) self.fget = fget return self def __get__( self, owner: Optional['Settings'], owner_type=None ) -> Union[Any, 'Setting']: # == class-level access == if not owner: return self if self.fget is None: raise AttributeError("Unreadable attribute") return self.get_value(owner) def get_value(self, owner: 'Settings'): return self.fget(owner) def __set__(self, owner: 'Settings', val): raise AttributeError("Can't set attribute: property setting cannot be set")