Source code for pyunity.values.abc

## Copyright (c) 2020-2022 The PyUnity Team
## This file is licensed under the MIT License.
## See https://docs.pyunity.x10.bz/en/latest/license.html

__all__ = ["ABCMessage", "ABCException", "ABCMeta",
           "abstractmethod", "abstractproperty"]

import inspect
from .other import IncludeMixin

[docs]class ABCException(Exception): pass
[docs]class ABCMessage(ABCException): pass
[docs]class abstractmethod(IncludeMixin): def __init__(self, func): if not callable(func): raise ABCException(f"Function is not callable: {func}") self.func = func self.args = self.getargs(func) def __eq__(self, other): if isinstance(other, abstractmethod): return self.args == other.args else: return self.args == self.getargs(other) def __get__(self, instance, owner=None): return self.func
[docs] @staticmethod def getargs(func): signature = inspect.signature(func) return [(param.name, param.kind) for param in signature.parameters.values()]
[docs]class abstractproperty(abstractmethod): def __get__(self, instance, owner=None): if instance is None: return self.func return self.func(instance) def __set__(self, instance, value): raise NotImplementedError def __eq__(self, other): if isinstance(other, property): return self.func.__name__ == other.fget.__name__ return False
[docs]class ABCMeta(type): _trigger = True def __init__(cls, fullname, bases, attrs): super().__init__(fullname, bases, attrs) for supercls in cls.__bases__: if supercls is object: continue methods = {attr: v for attr, v in supercls.__dict__.items() if isinstance(v, abstractmethod)} for method in methods: if cls._trigger and method not in attrs: raise ABCException("Method has not been defined: " + repr(methods[method].func)) if cls._trigger and methods[method] != attrs[method]: raise ABCException("Function signature is not the same: " + repr(methods[method].func) + " and " + repr(attrs[method])) @classmethod def __prepare__(cls, name, bases, message=None): if message is not None: raise ABCMessage(message) return super(ABCMeta, cls).__prepare__(name, bases)