Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/evn python3
- import functools
- buffer = set()
- class WithFinals(type):
- def __init__(cls, name, bases, dct):
- finals = set()
- # updating finals
- for base in bases:
- if hasattr(base, 'finals'):
- finals.update(base.finals)
- # creating methods
- def get_methods(cls_dct):
- meths = set()
- for key in cls_dct:
- if callable(cls_dct[key]):
- meths.add(key)
- return meths
- methods = get_methods(dct)
- if len(methods & finals) >= 1:
- raise AttributeError
- for item in buffer:
- if item in finals:
- raise AttributeError
- else:
- finals.add(item.__name__)
- # check parents in mro
- mro = cls.mro()[1:-1]
- if len(mro) >= 2:
- ln = len(mro) - 1
- if type(mro[ln]) is WithFinals:
- united_finals = mro[ln].finals
- else:
- united_finals = set()
- for i in range(ln, 0, -1):
- if type(mro[i - 1]) is WithFinals:
- cls_finals = mro[i - 1].finals
- cls_methods = mro[i - 1].methods
- else:
- cls_finals = set()
- cls_methods = get_methods(mro[i - 1].__dict__)
- if len(united_finals & cls_finals) >= 1 or \
- len(united_finals & cls_methods) >= 1:
- raise AttributeError
- united_finals |= cls_finals
- super(WithFinals, cls).__init__(name, bases, dct)
- setattr(cls, 'finals', finals)
- setattr(cls, 'methods', methods)
- buffer.clear()
- def final(method):
- buffer.add(method)
- @functools.wraps(method)
- def inner(self, *args, **kwargs):
- return method(self, *args, **kwargs)
- return inner
- class A(metaclass=WithFinals):
- @final
- def foo(self):
- pass
- class X(metaclass=WithFinals):
- @final
- def foo(self):
- pass
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement