Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import types
- from functools import wraps
- from copy import copy
- def private_context(method):
- @wraps(method)
- def wrapper(self, *args, **kwargs):
- try:
- object.__setattr__(self, '__private_context__', True)
- return method(self, *args, **kwargs)
- finally:
- object.__setattr__(self, '__private_context__', False)
- return wrapper
- class PrivateProperty(property):
- def __init__(self, prop):
- fget = private_context(prop.fget) if prop.fget else None
- fset = private_context(prop.fset) if prop.fset else None
- fdel = private_context(prop.fdel) if prop.fdel else None
- doc = prop.__doc__
- super().__init__(fget, fset, fdel, doc)
- class MetaPrivate(type):
- """Allows the definition of private methods
- It has two modes of operation:
- If you set __private__ as a list of private attributes,
- the only private methods and attributes are the ones in the list
- If you set __public__ as a list of public attributes,
- all attributes and methods become private, except the ones in the list
- """
- def __new__(cls, name, bases, dct):
- if '__private__' in dct or '__public__' in dct:
- private = set(dct.get('__private__', []))
- public = set(dct.get('__public__', []))
- new_dct = copy(dct)
- def accessible_key(self, key):
- is_public = key in public
- is_private = '__public__' in dct or key in private
- in_private_context = object.__getattribute__(self, '__private_context__')
- return is_public or not is_private or in_private_context
- def __getattribute__(self, key):
- if accessible_key(self, key):
- return object.__getattribute__(self, key)
- raise AttributeError(f'Attempt to access private attribute "{key}"')
- def __setattr__(self, key, value):
- if accessible_key(self, key):
- return object.__setattr__(self, key, value)
- raise AttributeError(f'Attempt to set private attribute "{key}"')
- new_dct['__private_context__'] = False
- new_dct['__getattribute__'] = __getattribute__
- new_dct['__setattr__'] = __setattr__
- for key, value in dct.items():
- if isinstance(value, types.FunctionType):
- new_dct[key] = private_context(value)
- if isinstance(value, property):
- new_dct[key] = PrivateProperty(value)
- dct = new_dct
- result = super().__new__(cls, name, bases, dct)
- return result
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement