Source code for treetensor.utils.clazz

"""
Class decorators.

Mainly used for tagging the members of a class, will be used when auto generating the documentation.
"""
import types
from functools import reduce
from operator import __or__
from typing import Iterable, TypeVar

__all__ = [
    'tag_names', 'inherit_names', 'current_names',
]

_DOC_TAG = '__doc_names__'
_CLS_TYPE = TypeVar('_CLS_TYPE', bound=type)


def _get_names(clazz: type):
    return set(getattr(clazz, _DOC_TAG, set()))


def _set_names(clazz: type, names: Iterable[str]):
    setattr(clazz, _DOC_TAG, set(names))


[docs]def tag_names(names: Iterable[str], keep: bool = True): def _decorator(cls: _CLS_TYPE) -> _CLS_TYPE: _old_names = _get_names(cls) if keep else set() _set_names(cls, set(names) | _old_names) return cls return _decorator
[docs]def inherit_names(*clazzes: type, keep: bool = True): def _decorator(cls: _CLS_TYPE) -> _CLS_TYPE: _old_names = _get_names(cls) if keep else set() _set_names(cls, reduce(__or__, [_old_names, *map(_get_names, clazzes)])) return cls return _decorator
class _TempClazz: @property def prop(self): return None PropertyType = type(_TempClazz.prop) def _is_property(clazz, name): prop = getattr(clazz, name) return isinstance(prop, PropertyType) and ( not hasattr(clazz.__base__, name) or getattr(clazz.__base__, name) is not prop ) # noinspection PyTypeChecker def _is_func(clazz, name): func = getattr(clazz, name) return isinstance(func, types.FunctionType) and ( not hasattr(clazz.__base__, name) or getattr(clazz.__base__, name) is not func ) def _is_classmethod(clazz, name): method = getattr(clazz, name) return isinstance(method, types.MethodType) and ( not hasattr(clazz.__base__, name) or getattr(clazz.__base__, name).__func__ is not method.__func__ )
[docs]def current_names(keep: bool = True): def _decorator(cls: _CLS_TYPE) -> _CLS_TYPE: members = set() for name in dir(cls): item = getattr(cls, name) if ((_is_func(cls, name) or _is_classmethod(cls, name)) and getattr(item, '__name__', None) == name) or \ (_is_property(cls, name)): members.add(name) _old_names = _get_names(cls) if keep else set() _set_names(cls, _old_names | set(members)) return cls return _decorator