Source code for Muscat.Helpers.Decorators

# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
from functools import wraps


useFroze_itDecorator = True

# https://stackoverflow.com/questions/3603502/prevent-creating-new-attributes-outside-init
# https://hynek.me/articles/hasattr/
sentinel = object()
# for the moment if a class is frozen no heritage is possible ... working on a solution


[docs] def UnFrozen(self): self.__frozen = False
[docs] def IsFrozen(self): return self.__frozen
[docs] def always_froze_it(cls): #cls.__frozen = False setattr(cls,"__frozen",False) setattr(cls,"UnFrozen",UnFrozen) setattr(cls,"IsFrozen",IsFrozen) def frozensetattr(self, key, value): #y = getattr(self, key, sentinel) if self.__frozen and not hasattr(self,key) : raise Exception(f"Class {cls.__name__} is frozen. Cannot set {key} = {value}") else: object.__setattr__(self, key, value) def init_decorator(func): @wraps(func) def wrapper(self, *args, **kwargs): func(self, *args, **kwargs) self.__frozen = True return wrapper cls.__setattr__ = frozensetattr cls.__init__ = init_decorator(cls.__init__) return cls
[docs] def froze_it(cls): """ Decorator to make the class immutable (no more attributes can be added after initialization) For the moment if a class is frozen no heritage is possible. The user must unfrozen the class before adding new attributes. .. code-block:: python self.UnFrozen() the module level attribute useFroze_itDecorator is use to determine if this decorator must be applied. """ if not useFroze_itDecorator: # pragma: no coverage setattr(cls, "UnFrozen", lambda x: None) setattr(cls, "IsFrozen", lambda x: False) return cls return always_froze_it(cls)
[docs] def CheckIntegrity(GUI:bool=False): @always_froze_it class FrozenTest(): def __init__(self) -> None: self.a = 3 @always_froze_it class FrozenSubClass(FrozenTest): def __init__(self) -> None: super().__init__() self.UnFrozen() self.b = 50 obj1 = FrozenTest() assert obj1.IsFrozen() obj2 = FrozenSubClass() if useFroze_itDecorator: obj = FrozenTest() obj.a = 5 try: obj.b = 7 return "Error in a frozen class" # pragma: no coverage except Exception as inst: pass print(inst) print("This error message is normal") obj.__frozen = False obj.b = 7 obj = FrozenSubClass() obj.b = 5 try: obj.c = 7 return "Error in frozen subclass" # pragma: no coverage except Exception as inst: pass obj.UnFrozen() obj.c = 7 return "ok"
if __name__ == '__main__': print(CheckIntegrity(True)) # pragma: no cover