Advertisement
Guest User

Untitled

a guest
Apr 3rd, 2024
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.84 KB | None | 0 0
  1. import inspect
  2. import typing
  3.  
  4.  
  5. def strict(cls: typing.Type):
  6.     class_name = cls.__name__ + "Cover"
  7.     original_setattr = cls.__setattr__
  8.  
  9.     # Overridden __setattr__ for the original class
  10.     def new_setattr(self, name, value):
  11.         original_setattr(self, name, value)
  12.         # Update the cover class if attribute is public
  13.         if not name.startswith('_') and hasattr(self, '_cover') and getattr(self._cover, name) != value:
  14.             setattr(self._cover, name, value)
  15.  
  16.     # Replace __setattr__ in the original class
  17.     cls.__setattr__ = new_setattr
  18.  
  19.     # Define new __init__ for the cover class
  20.     def new_init(self, *args, **kwargs):
  21.         # Create an instance of the original class
  22.         original_instance = cls(*args, **kwargs)
  23.         original_instance._cover = self  # Reference to the cover class
  24.  
  25.         # Bind public methods and attributes to the cover class instance
  26.         for attr_name in dir(original_instance):
  27.             if not attr_name.startswith('_'):  # or attr_name in ('__dict__', '__module__'):
  28.                 attr_value = getattr(original_instance, attr_name)
  29.                 if inspect.isfunction(attr_value):
  30.                     setattr(self, attr_name, attr_value.__get__(self, cls))
  31.                 else:
  32.                     setattr(self, attr_name, attr_value)
  33.  
  34.         def custom_setattr(instance, name, value):
  35.             object.__setattr__(instance, name, value)
  36.             if not name.startswith('_') and getattr(original_instance, name) != value:
  37.                 setattr(original_instance, name, value)
  38.  
  39.         self._dynamic_setattr = custom_setattr
  40.  
  41.         # Remove reference to original instance
  42.         # del original_instance
  43.  
  44.     def setattr_overwrite(self, name, value):
  45.         if hasattr(self, '_dynamic_setattr'):
  46.             self._dynamic_setattr(self, name, value)
  47.         else:
  48.             object.__setattr__(self, name, value)
  49.  
  50.     # Create a new cover class with the new __init__ and other methods/attributes
  51.     cover_class_attrs = {
  52.         '__init__': new_init,
  53.         '__class__': cls,
  54.         '__setattr__': setattr_overwrite,
  55.     }
  56.     for attr_name in dir(cls):
  57.         if callable(getattr(cls, attr_name)) and not attr_name.startswith('_'):
  58.             cover_class_attrs[attr_name] = getattr(cls, attr_name)
  59.  
  60.     CoverClass = type(class_name, (object,), cover_class_attrs)
  61.     return CoverClass
  62.  
  63.  
  64. @strict
  65. class Test:
  66.     _hello = 0
  67.  
  68.     def __init__(self):
  69.         self.herlo = 1
  70.  
  71.     def change_attr(self):
  72.         self.herlo = 1
  73.         self._hello += self.herlo
  74.  
  75.     def printer(self):
  76.         print(self.herlo, self._hello)
  77.  
  78.  
  79. # Testing
  80. test = Test()
  81. test.printer()
  82. test.change_attr()
  83. test.printer()
  84. test.herlo = 2
  85. test.change_attr()
  86. test.printer()  # Should output 2, 3
  87. print(test.herlo)  # Should output 2
  88. print(test._hello)
  89.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement