# Path: soap/common/cache.py
# class Flyweight(object):
# 
#     _cache = weakref.WeakValueDictionary()
# 
#     def __new__(cls, *args, **kwargs):
#         if not args and not kwargs:
#             return object.__new__(cls)
#         key = pickle.dumps((cls, args, list(kwargs.items())))
#         v = cls._cache.get(key, None)
#         if v is not None:
#             return v
#         v = object.__new__(cls)
#         cls._cache[key] = v
#         return v


import functools
from soap.common.cache import Flyweight



def _decorate(cls):
    if not hasattr(cls, '_decorated'):
        cls._decorated = set()
    if cls is Lattice or cls in cls._decorated:
        return

    def decorate_self(base_func, decd_func):
        if not decd_func:
            raise ValueError(
                'No function matching {} from class {} to decorate'.format(
                    base_func.__qualname__, cls))

        @functools.wraps(decd_func)
        def wrapper(self):
            t = base_func(self)
            if t is not None:
                return t
            return decd_func(self)

        return wrapper

    def decorate_self_other(base_func, decd_func):
        if not decd_func:
            raise ValueError('No matching {} function to decorate'.format(
                base_func.__qualname__))


# Path: soap/common/cache.py
# class Flyweight(object):
# 
#     _cache = weakref.WeakValueDictionary()
# 
#     def __new__(cls, *args, **kwargs):
#         if not args and not kwargs:
#             return object.__new__(cls)
#         key = pickle.dumps((cls, args, list(kwargs.items())))
#         v = cls._cache.get(key, None)
#         if v is not None:
#             return v
#         v = object.__new__(cls)
#         cls._cache[key] = v
#         return v


# Path: soap/lattice/base.py
import functools
from soap.common.cache import Flyweight




def _decorate(cls):
    if not hasattr(cls, '_decorated'):
        cls._decorated = set()
    if cls is Lattice or cls in cls._decorated:
        return

    def decorate_self(base_func, decd_func):
        if not decd_func:
            raise ValueError(
                'No function matching {} from class {} to decorate'.format(
                    base_func.__qualname__, cls))

        @functools.wraps(decd_func)
        def wrapper(self):
            t = base_func(self)
            if t is not None:
                return t
            return decd_func(self)

        return wrapper

    def decorate_self_other(base_func, decd_func):
        if not decd_func:
            raise ValueError('No matching {} function to decorate'.format(
                base_func.__qualname__))


        @functools.wraps(decd_func)